add customers and staffs
This commit is contained in:
@@ -48,7 +48,9 @@
|
||||
"language.selection.title":"Please select your language",
|
||||
|
||||
"welcome.signin":"Sign In",
|
||||
"welcome.msg":"Welcome to FCS Logistics!",
|
||||
"welcome.msg":"Welcome to FCS!",
|
||||
|
||||
"home.invitation.request.msg":"We are working on your invitation request!",
|
||||
|
||||
"sms.verify.title":"Verify your number",
|
||||
"sms.six.digit":"Enter 6 digit sms code sent to",
|
||||
@@ -60,10 +62,44 @@
|
||||
"invite.request":"Request Invitation",
|
||||
"invite.request.successful":"Successfully requested!",
|
||||
|
||||
"================================================================":"",
|
||||
"customer.list.title":"Customers",
|
||||
"customer.name":"Name",
|
||||
"customer.phone":"Phone Number",
|
||||
"customer.status":"Status",
|
||||
"customer.fcs.id":"FCS ID",
|
||||
"customer.invitation.request.confirm":"Accept Customer",
|
||||
|
||||
"invitation.list": "Invitations",
|
||||
"invitation.edit": "Invitation",
|
||||
"invitation.new": "New Invitation",
|
||||
"invitation.confirm.delete": "Delete this invitation?",
|
||||
|
||||
"staff.title":"Staffs",
|
||||
"staff.list.title":"Staffs",
|
||||
"staff.new":"New Staff",
|
||||
"staff.form.title":"Staff",
|
||||
"staff.add":"Add",
|
||||
"staff.update":"Update",
|
||||
|
||||
"profile.title": "My Profile",
|
||||
"profile.edit_title": "Edit My Profile",
|
||||
"profile.name": "Name",
|
||||
"profile.phone": "Phone",
|
||||
"profile.language": "Languages",
|
||||
"profile.logout": "logout",
|
||||
"profile.usa.shipping.address": "USA Shipping Address",
|
||||
"profile.logout.confirm":"Are you sure want to logout?",
|
||||
"profile.devices":"Devices",
|
||||
"profile.email":"Email",
|
||||
"profile.privilege":"Privilege",
|
||||
|
||||
|
||||
"btn.save": "Save",
|
||||
"btn.approve":"Approve",
|
||||
"btn.delete":"Delete",
|
||||
|
||||
"================================================================":"",
|
||||
|
||||
|
||||
"product": "Product",
|
||||
"price": "Price",
|
||||
@@ -167,16 +203,7 @@
|
||||
"reg.confirm":"Submit Registration?",
|
||||
"reg.date":"Registeration Date",
|
||||
|
||||
"profile.title": "Profile",
|
||||
"profile.edit_title": "Edit FCS Profile",
|
||||
"profile.name": "Name",
|
||||
"profile.phone": "Phone",
|
||||
"profile.language": "Languages",
|
||||
"profile.logout": "logout",
|
||||
"profile.logout.confirm":"Are you sure want to logout?",
|
||||
"profile.devices":"Devices",
|
||||
"profile.email":"Email",
|
||||
"profile.privilege":"Privilege",
|
||||
|
||||
|
||||
"device.confirm":"Confirm this device?",
|
||||
"device.logout":"Logout this device?",
|
||||
@@ -530,12 +557,6 @@
|
||||
|
||||
"notifications.title":"Notification",
|
||||
|
||||
"staff.title":"Staffs",
|
||||
"staff.list.title":"STAFFS",
|
||||
"staff.new":"New Staff",
|
||||
"staff.form.title":"STAFF",
|
||||
"staff.add":"Add",
|
||||
"staff.update":"Update",
|
||||
|
||||
"shipment.title":"FCS Shipments",
|
||||
"shipment.list.title":"FCS SHIPMENTS",
|
||||
@@ -605,9 +626,6 @@
|
||||
"invoice.add_package":"Add Package",
|
||||
|
||||
|
||||
"customer.list.title":"CUSTOMERS",
|
||||
"customer.form.title":"CUSTOMER",
|
||||
"customer.invite":"Invite",
|
||||
|
||||
"fcs.btn": "FCS Profile",
|
||||
"fcs.profile": "FCS PROFILE",
|
||||
|
||||
@@ -48,7 +48,9 @@
|
||||
"language.selection.title":"ဘာသာစကား ရွေးချယ်ပါ",
|
||||
|
||||
"welcome.signin":"ဝင်မည်",
|
||||
"welcome.msg":"FCS Logistics က ကြိုဆိုပါတယ်!",
|
||||
"welcome.msg":"FCS က ကြိုဆိုပါတယ်!",
|
||||
|
||||
"home.invitation.request.msg":"ဖိတ်ကြားမှု တောင်းဆိုသည်ကို လုပ်ဆောင်နေပါသည်!",
|
||||
|
||||
"sms.verify.title":"သင့်နံပါတ်ကိုအတည်ပြုပါ",
|
||||
"sms.six.digit":"SMS ဂဏန်း ခြောက်လုံး ကိုရိုက်ထဲ့ပါ",
|
||||
@@ -60,11 +62,43 @@
|
||||
"invite.request":"ဖိတ်ကြားမှု တောင်းဆိုမည်",
|
||||
"invite.request.successful":"တောင်းဆိုမှု အောင်မြင်သည်!",
|
||||
|
||||
"================================================================":"",
|
||||
"customer.list.title":"ဝယ်ယူသူများ",
|
||||
"customer.name":"နာမည်",
|
||||
"customer.phone":"ဖုန်းနံပါတ်",
|
||||
"customer.status":"အခြေအနေ",
|
||||
"customer.fcs.id":"FCS ID",
|
||||
"customer.invitation.request.confirm":"လက်ခံ လိုက်ပါ",
|
||||
|
||||
"invitation.list": "ဖိတ်ကြားမှုများ",
|
||||
"invitation.edit": "ဖိတ်ကြားမှု",
|
||||
"invitation.new": "ဖိတ်ကြားမှု အသစ်",
|
||||
"invitation.confirm.delete": "ဖိတ်ကြားမှု ဖျက်မလား?",
|
||||
|
||||
"staff.title":"ဝန်ထမ်းများ",
|
||||
"staff.list.title":"ဝန်ထမ်းများ",
|
||||
"staff.new":"ဝန်ထမ်း အသစ်",
|
||||
"staff.form.title":"ဝန်ထမ်း",
|
||||
"staff.add":"အသစ်ထည့်မည်",
|
||||
"staff.update":"ပြုပြင်မည်",
|
||||
|
||||
"profile.title":"ကျွန်ုပ် ပရိုဖိုင်",
|
||||
"profile.edit_title":"ကျွန်ုပ် ပရိုဖိုင်ကိုပြုပြင်ရန်",
|
||||
"profile.name":"နာမည်",
|
||||
"profile.phone": "ဖုန်းနံပါတ်",
|
||||
"profile.language": "ဘာသာစကားများ",
|
||||
"profile.logout": "အကောင့်ထွက်ရန်",
|
||||
"profile.usa.shipping.address": "အမေရိကား ပစည်းပို့ရန်လိပ်စာ",
|
||||
"profile.logout.confirm":"အကောင့်ထွက်ရန်သေချာပြီလား?",
|
||||
"profile.devices":"ဖုန်းမော်ဒယ်အမျိုးအစားများ",
|
||||
"profile.email":"အီးမေးလ်",
|
||||
"profile.privilege":"လုပ်ပိုင်ခွင့်",
|
||||
|
||||
"btn.save":"သိမ်းဆည်းရန်",
|
||||
"btn.approve":"အတည်ပြုရန်",
|
||||
"btn.delete":"ဖျက်ရန်",
|
||||
"================================================================":"",
|
||||
|
||||
|
||||
|
||||
"product": "ကုန်ပစ္စည်း",
|
||||
"price": "ဈေးနှုန်း",
|
||||
@@ -166,17 +200,6 @@
|
||||
"reg.confirm":"မှတ်ပုံတင်သွင်းမည်လား?",
|
||||
"reg.date":"မှတ်ပုံတင်သည့် နေ့စွဲ",
|
||||
|
||||
"profile.title":"ပရိုဖိုင်",
|
||||
"profile.edit_title":"ပရိုဖိုင်ကိုပြုပြင်ရန်",
|
||||
"profile.name":"နာမည်",
|
||||
"profile.phone": "ဖုန်းနံပါတ်",
|
||||
"profile.language": "ဘာသာစကားများ",
|
||||
"profile.logout": "အကောင့်ထွက်ရန်",
|
||||
"profile.logout.confirm":"အကောင့်ထွက်ရန်သေချာပြီလား?",
|
||||
"profile.devices":"ဖုန်းမော်ဒယ်အမျိုးအစားများ",
|
||||
"profile.email":"အီးမေးလ်",
|
||||
"profile.privilege":"လုပ်ပိုင်ခွင့်",
|
||||
|
||||
"device.confirm":"ဒီဖုန်းမော်ဒယ်ကိုအတည်ပြုမည်လား?",
|
||||
"device.logout":"ဒီဖုန်းမော်ဒယ်ကိုထွက်ရန်သေချာပြီလား?",
|
||||
"device.set_primary":"ဒီဖုန်းမော်ဒယ်ကိုမူလမော်ဒယ်ထည့်ရန်သေချာပြီလား?",
|
||||
@@ -561,19 +584,11 @@
|
||||
|
||||
"notifications.title":"Notifications",
|
||||
|
||||
"staff.title":"FCS ဝန်ထမ်းများ",
|
||||
"staff.list.title":"FCS ဝန်ထမ်းများ",
|
||||
"staff.new":"New Staff",
|
||||
"staff.form.title":"FCS STAFF",
|
||||
"staff.add":"Add",
|
||||
"staff.update":"Update",
|
||||
|
||||
"shipment.title":"FCS တင်ပို့ခြင်းများ",
|
||||
"shipment.list.title":"FCS တင်ပို့ခြင်းများ",
|
||||
"shipment.add":"New FCS shipment",
|
||||
"shipment.form.title":"FCS SHIPMENT",
|
||||
"shipment.number":"FCS Shipment Number",
|
||||
|
||||
|
||||
"package.name":"Packages",
|
||||
"package.title":"PACKAGES",
|
||||
@@ -611,7 +626,6 @@
|
||||
|
||||
"customers.btn": "ဝယ်ယူသူများ",
|
||||
"customers.title": "ဝယ်ယူသူများ",
|
||||
"customer.invite":"Invite",
|
||||
|
||||
"invoices.btn": "ငွေတောင်းခံလွှာများ",
|
||||
"invoices.title": "ငွေတောင်းခံလွှာများ",
|
||||
@@ -622,8 +636,6 @@
|
||||
"invoice.add_box":"Add Box",
|
||||
|
||||
|
||||
"customer.list.title":"ဝယ်ယူသူများ",
|
||||
"customer.form.title":"ဝယ်ယူသူ",
|
||||
|
||||
"fcs.profile": "ပရိုဖိုင်",
|
||||
|
||||
|
||||
21
lib/app.dart
21
lib/app.dart
@@ -1,6 +1,5 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:fcs/fcs/common/helpers/theme.dart';
|
||||
import 'package:fcs/fcs/common/localization/app_translations_delegate.dart';
|
||||
import 'package:fcs/fcs/common/localization/transalation.dart';
|
||||
import 'package:fcs/fcs/common/pages/contact/model/contact_model.dart';
|
||||
@@ -8,7 +7,8 @@ import 'package:fcs/fcs/common/pages/customers/model/customer_model.dart';
|
||||
import 'package:fcs/fcs/common/pages/faq/model/faq_model.dart';
|
||||
import 'package:fcs/fcs/common/pages/initial_language_selection.dart';
|
||||
import 'package:fcs/fcs/common/pages/model/language_model.dart';
|
||||
import 'package:fcs/fcs/common/pages/signin/model/signin_model.dart';
|
||||
import 'package:fcs/fcs/common/pages/model/main_model.dart' as fcs;
|
||||
import 'package:fcs/fcs/common/pages/staff/model/staff_model.dart';
|
||||
import 'package:fcs/fcs/common/pages/term/model/term_model.dart';
|
||||
import 'package:fcs/fcs/common/services/services.dart';
|
||||
import 'package:fcs/model/buyer_model.dart';
|
||||
@@ -31,8 +31,10 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
|
||||
import 'package:flutter_localizations/flutter_localizations.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:fcs/fcs/common/pages/model/main_model.dart' as fcs;
|
||||
|
||||
import 'fcs/common/pages/home_page.dart';
|
||||
import 'fcs/common/pages/splash_page.dart';
|
||||
import 'fcs/common/pages/welcome_page.dart';
|
||||
import 'model/announcement_model.dart';
|
||||
import 'model/chart_model.dart';
|
||||
import 'model/device_model.dart';
|
||||
@@ -48,9 +50,6 @@ import 'model/report_user_model.dart';
|
||||
import 'model/shipment_rate_model.dart';
|
||||
import 'model/user_model.dart';
|
||||
import 'model_fcs/box_model.dart';
|
||||
import 'fcs/common/pages/home_page.dart';
|
||||
import 'fcs/common/pages/welcome_page.dart';
|
||||
import 'fcs/common/pages/splash_page.dart';
|
||||
import 'pages/term.dart';
|
||||
|
||||
class App extends StatefulWidget {
|
||||
@@ -67,7 +66,6 @@ class _AppState extends State<App> {
|
||||
|
||||
final UserModel userModel = new UserModel();
|
||||
final ProductModel productModel = new ProductModel();
|
||||
final EmployeeModel employeeModel = new EmployeeModel();
|
||||
final POSubmissionModel poSubmissionModel = new POSubmissionModel();
|
||||
final DOModel doModel = new DOModel();
|
||||
final LanguageModel lanuguageModel = new LanguageModel();
|
||||
@@ -94,7 +92,7 @@ class _AppState extends State<App> {
|
||||
final InvoiceModel invoiceModel = new InvoiceModel();
|
||||
final CustomerModel customerModel = new CustomerModel();
|
||||
final DiscountModel discountModel = new DiscountModel();
|
||||
final SigninModel signinModel = new SigninModel();
|
||||
final StaffModel staffModel = new StaffModel();
|
||||
|
||||
AppTranslationsDelegate _newLocaleDelegate;
|
||||
static FlutterLocalNotificationsPlugin _flutterLocalNotificationsPlugin =
|
||||
@@ -103,12 +101,14 @@ class _AppState extends State<App> {
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
mainModel2..addModel(customerModel);
|
||||
mainModel2..addModel(staffModel);
|
||||
mainModel2.init();
|
||||
|
||||
_newLocaleDelegate = AppTranslationsDelegate(newLocale: null);
|
||||
Translation().onLocaleChanged = onLocaleChange;
|
||||
mainModel
|
||||
..addModel(userModel)
|
||||
..addModel(employeeModel)
|
||||
..addModel(storageModel)
|
||||
..addModel(regModel)
|
||||
..addModel(poSubmissionModel)
|
||||
@@ -225,7 +225,7 @@ class _AppState extends State<App> {
|
||||
ChangeNotifierProvider.value(value: mainModel),
|
||||
ChangeNotifierProvider.value(value: userModel),
|
||||
ChangeNotifierProvider.value(value: productModel),
|
||||
ChangeNotifierProvider.value(value: employeeModel),
|
||||
ChangeNotifierProvider.value(value: staffModel),
|
||||
ChangeNotifierProvider.value(value: poSubmissionModel),
|
||||
ChangeNotifierProvider.value(value: doModel),
|
||||
ChangeNotifierProvider.value(value: storageModel),
|
||||
@@ -255,7 +255,6 @@ class _AppState extends State<App> {
|
||||
ChangeNotifierProvider.value(value: contactModel),
|
||||
ChangeNotifierProvider.value(value: termModel),
|
||||
ChangeNotifierProvider.value(value: faqModel),
|
||||
ChangeNotifierProvider.value(value: signinModel),
|
||||
],
|
||||
child: Consumer<LanguageModel>(
|
||||
builder: (context, value, child) {
|
||||
|
||||
@@ -9,10 +9,13 @@ import 'package:fcs/fcs/common/domain/entities/setting.dart';
|
||||
import 'package:fcs/fcs/common/domain/entities/user.dart';
|
||||
import 'package:fcs/fcs/common/domain/exceiptions/signin_exception.dart';
|
||||
import 'package:firebase_auth/firebase_auth.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
|
||||
import '../../helpers/api_helper.dart';
|
||||
|
||||
class AuthFb {
|
||||
final log = Logger('AuthFb');
|
||||
|
||||
static final AuthFb instance = AuthFb._();
|
||||
AuthFb._();
|
||||
|
||||
@@ -21,12 +24,22 @@ class AuthFb {
|
||||
|
||||
Future<fcs.AuthResult> sendSmsCodeToPhoneNumber(String phoneNumber) {
|
||||
Completer<fcs.AuthResult> completer = Completer();
|
||||
bool codeSentCompleted = false;
|
||||
|
||||
final PhoneVerificationCompleted verificationCompleted =
|
||||
(AuthCredential credential) async {
|
||||
AuthResult _authResult = await _fb.signInWithCredential(credential);
|
||||
if (_authResult == null) {
|
||||
throw SigninException("Sigin error!");
|
||||
AuthResult _authResult;
|
||||
try {
|
||||
_authResult = await _fb.signInWithCredential(credential);
|
||||
print("PhoneVerificationCompleted :$_authResult");
|
||||
if (_authResult == null) {
|
||||
throw SigninException("Sigin error!");
|
||||
}
|
||||
} catch (e) {
|
||||
print("Exception:$e");
|
||||
// throw e;
|
||||
completer.completeError(SigninException(e.toString()));
|
||||
return;
|
||||
}
|
||||
fcs.AuthResult auth =
|
||||
fcs.AuthResult(authStatus: AuthStatus.AUTH_VERIFIED);
|
||||
@@ -39,25 +52,32 @@ class AuthFb {
|
||||
(AuthException authException) async {
|
||||
print(
|
||||
'Phone number verification failed. Code: ${authException.code}. Message: ${authException.message}');
|
||||
completer
|
||||
.completeError(SigninException("Phone number verification failed"));
|
||||
completer.completeError(SigninException(
|
||||
"Phone number verification failed:${authException.message}"));
|
||||
};
|
||||
|
||||
final PhoneCodeSent codeSent =
|
||||
(String verificationId, [int forceResendingToken]) async {
|
||||
_verificationId = verificationId;
|
||||
print("code sent to " + phoneNumber);
|
||||
completer.complete(fcs.AuthResult(authStatus: AuthStatus.SMS_SENT));
|
||||
print("codeSent " + phoneNumber);
|
||||
codeSentCompleted = true;
|
||||
};
|
||||
|
||||
final PhoneCodeAutoRetrievalTimeout codeAutoRetrievalTimeout =
|
||||
(String verificationId) {
|
||||
print("codeAutoRetrievalTimeout $verificationId ");
|
||||
|
||||
_verificationId = verificationId;
|
||||
if (codeSentCompleted) {
|
||||
completer.complete(fcs.AuthResult(authStatus: AuthStatus.SMS_SENT));
|
||||
} else {
|
||||
completer.completeError(SigninException("SMS code failed"));
|
||||
}
|
||||
};
|
||||
|
||||
_fb.verifyPhoneNumber(
|
||||
phoneNumber: phoneNumber,
|
||||
timeout: const Duration(minutes: 2),
|
||||
timeout: const Duration(seconds: 0),
|
||||
verificationCompleted: verificationCompleted,
|
||||
verificationFailed: verificationFailed,
|
||||
codeSent: codeSent,
|
||||
@@ -102,12 +122,12 @@ class AuthFb {
|
||||
if (firebaseUser == null) return null;
|
||||
IdTokenResult idToken =
|
||||
await firebaseUser.getIdToken(refresh: refreshIdToken);
|
||||
String name = idToken.claims["name"];
|
||||
|
||||
log.info("Claims:${idToken.claims}");
|
||||
|
||||
User user = User();
|
||||
user.id = firebaseUser.uid;
|
||||
user.name = name;
|
||||
user.hasSignup =
|
||||
idToken.claims.containsKey("signup") && idToken.claims["signup"];
|
||||
user.status = idToken.claims["status"];
|
||||
user.phoneNumber = firebaseUser.phoneNumber;
|
||||
|
||||
// add privileges
|
||||
@@ -115,10 +135,24 @@ class AuthFb {
|
||||
if (privileges != null && privileges != "") {
|
||||
user.privileges = privileges.split(":").toList();
|
||||
}
|
||||
|
||||
User _user = await getUserFromFirestore(user.id);
|
||||
user.fcsID = _user.fcsID;
|
||||
user.name = _user.name;
|
||||
return user;
|
||||
}
|
||||
|
||||
Future<User> getUserFromFirestore(String userID) async {
|
||||
DocumentSnapshot snap = await Firestore.instance
|
||||
.collection(user_collection)
|
||||
.document(userID)
|
||||
.get();
|
||||
if (snap.exists) {
|
||||
User user = User.fromMap(snap.data, snap.documentID);
|
||||
return user;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
Future<bool> isLogin() async {
|
||||
final FirebaseUser firebaseUser = await _fb.currentUser();
|
||||
return Future.value(firebaseUser != null);
|
||||
@@ -134,6 +168,17 @@ class AuthFb {
|
||||
return getUser(refreshIdToken: true);
|
||||
}
|
||||
|
||||
Future<bool> hasInvite() async {
|
||||
var invited =
|
||||
await requestAPI("/check_invitation", "GET", token: await getToken());
|
||||
return invited["invited"];
|
||||
}
|
||||
|
||||
Future<void> updateProfile(String newUserName) async {
|
||||
return await requestAPI("/profile", "PUT",
|
||||
payload: {"user_name": newUserName}, token: await getToken());
|
||||
}
|
||||
|
||||
Future<String> getToken() async {
|
||||
FirebaseUser firebaseUser = await _fb.currentUser();
|
||||
IdTokenResult token = await firebaseUser.getIdToken();
|
||||
|
||||
38
lib/fcs/common/data/providers/user_data_provider.dart
Normal file
38
lib/fcs/common/data/providers/user_data_provider.dart
Normal file
@@ -0,0 +1,38 @@
|
||||
import 'package:cloud_firestore/cloud_firestore.dart';
|
||||
import 'package:fcs/fcs/common/domain/constants.dart';
|
||||
import 'package:fcs/fcs/common/domain/entities/user.dart';
|
||||
import 'package:fcs/fcs/common/helpers/api_helper.dart';
|
||||
import 'package:fcs/fcs/common/helpers/firebase_helper.dart';
|
||||
|
||||
class UserDataProvider {
|
||||
Future<void> inviteUser(String userName, String phoneNumber) async {
|
||||
return await requestAPI("/invites", "POST",
|
||||
payload: {"user_name": userName, "phone_number": phoneNumber},
|
||||
token: await getToken());
|
||||
}
|
||||
|
||||
Future<void> deleteInvite(String phoneNumber) async {
|
||||
return await requestAPI("/invites", "DELETE",
|
||||
payload: {"phone_number": phoneNumber}, token: await getToken());
|
||||
}
|
||||
|
||||
Future<void> acceptRequest(String userID) async {
|
||||
return await requestAPI("/invites", "PUT",
|
||||
payload: {"id": userID}, token: await getToken());
|
||||
}
|
||||
|
||||
Future<User> findUser(String phoneNumber) async {
|
||||
QuerySnapshot querySnap = await Firestore.instance
|
||||
.collection(user_collection)
|
||||
.where("phone_number", isEqualTo: phoneNumber)
|
||||
.limit(1)
|
||||
.getDocuments();
|
||||
|
||||
if (querySnap.documents.length > 0) {
|
||||
var snap = querySnap.documents.first;
|
||||
User user = User.fromMap(snap.data, snap.documentID);
|
||||
return user;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
import 'package:fcs/fcs/common/domain/entities/user.dart';
|
||||
|
||||
class UserFBDataProvider {
|
||||
Future<User> getUser(String id) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,13 @@
|
||||
const ok_doc_id = "ok";
|
||||
const setting_doc_id = "setting";
|
||||
|
||||
const config_collection = "configs";
|
||||
const user_collection = "users";
|
||||
const invitations_collection = "invitations";
|
||||
const setting_doc_id = "setting";
|
||||
const privilege_collection = "privileges";
|
||||
|
||||
const ok_doc_id = "ok";
|
||||
|
||||
const biz_collection = "bizs";
|
||||
const product_collection = "products";
|
||||
const user_collection = "users";
|
||||
const privilege_collection = "privileges";
|
||||
const user_level_collection = "user_levels";
|
||||
const storage_collection = "storages";
|
||||
const buyer_collection = "buyers";
|
||||
|
||||
@@ -9,7 +9,6 @@ class Role {
|
||||
roleID = json['role_id'];
|
||||
privileges = json['privileges'];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class Parser {
|
||||
@@ -63,10 +62,6 @@ class UserLevel {
|
||||
UserLevel({this.id, this.name, this.level});
|
||||
|
||||
factory UserLevel.fromMap(Map<String, dynamic> map, String docID) {
|
||||
return UserLevel(
|
||||
id: docID,
|
||||
name: map['name'],
|
||||
level: map['level']
|
||||
);
|
||||
return UserLevel(id: docID, name: map['name'], level: map['level']);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,6 +22,8 @@ class Setting {
|
||||
String mmContactNumber;
|
||||
String emailAddress;
|
||||
String facebookLink;
|
||||
bool inviteRequired;
|
||||
String appUrl;
|
||||
|
||||
final String okEnergyId;
|
||||
final String about;
|
||||
@@ -84,6 +86,8 @@ class Setting {
|
||||
this.mmContactNumber,
|
||||
this.emailAddress,
|
||||
this.facebookLink,
|
||||
this.inviteRequired,
|
||||
this.appUrl,
|
||||
this.about,
|
||||
this.okEnergyId,
|
||||
this.terms,
|
||||
@@ -122,6 +126,8 @@ class Setting {
|
||||
|
||||
return Setting(
|
||||
supportBuildNum: map['support_build_number'],
|
||||
inviteRequired: map['invite_required'],
|
||||
appUrl: map['app_url'],
|
||||
usaAddress: map['usa_address'],
|
||||
mmAddress: map['mm_address'],
|
||||
usaContactNumber: map['usa_contact_number'],
|
||||
|
||||
@@ -1,22 +1,28 @@
|
||||
import 'package:fcs/fcs/common/helpers/const.dart';
|
||||
|
||||
class User {
|
||||
String id;
|
||||
String name;
|
||||
String phoneNumber;
|
||||
bool hasSignup;
|
||||
bool invited;
|
||||
List<String> privileges = [];
|
||||
|
||||
String status;
|
||||
String fcsID;
|
||||
|
||||
List<String> privileges = [];
|
||||
|
||||
String get phone => phoneNumber != null && phoneNumber.startsWith("959")
|
||||
? "0${phoneNumber.substring(2)}"
|
||||
: phoneNumber;
|
||||
|
||||
bool get joined => status != null && status == userStatusJoined;
|
||||
bool get invited => status != null && status == userStatusInvited;
|
||||
bool get requested => status != null && status == userStatusRequested;
|
||||
String get share => "Your phone number:$phoneNumber";
|
||||
User({
|
||||
this.id,
|
||||
this.name,
|
||||
this.phoneNumber,
|
||||
this.fcsID,
|
||||
this.status,
|
||||
this.privileges,
|
||||
});
|
||||
|
||||
factory User.fromJson(Map<String, dynamic> json) {
|
||||
@@ -24,6 +30,7 @@ class User {
|
||||
id: json['id'],
|
||||
name: json['user_name'],
|
||||
phoneNumber: json['phone_number'],
|
||||
status: json['status'],
|
||||
);
|
||||
}
|
||||
|
||||
@@ -41,11 +48,16 @@ class User {
|
||||
}
|
||||
|
||||
factory User.fromMap(Map<String, dynamic> map, String docID) {
|
||||
List<String> _privileges =
|
||||
map['privileges'] == null ? [] : map['privileges'].cast<String>();
|
||||
|
||||
return User(
|
||||
id: docID,
|
||||
name: map['user_name'],
|
||||
phoneNumber: map['phone_number'],
|
||||
);
|
||||
id: docID,
|
||||
name: map['user_name'],
|
||||
phoneNumber: map['phone_number'],
|
||||
status: map['status'],
|
||||
fcsID: map['fcs_id'],
|
||||
privileges: _privileges);
|
||||
}
|
||||
|
||||
bool isCustomer() {
|
||||
@@ -60,16 +72,26 @@ class User {
|
||||
return privileges != null ? privileges.contains('admin') : false;
|
||||
}
|
||||
|
||||
bool hasMaintenance() {
|
||||
return privileges != null ? privileges.contains('mt') : false;
|
||||
bool hasCustomers() {
|
||||
return hasSysAdmin() ||
|
||||
hasAdmin() ||
|
||||
(privileges != null ? privileges.contains('c') : false);
|
||||
}
|
||||
|
||||
bool hasCustomers() {
|
||||
return privileges != null ? privileges.contains('c') : false;
|
||||
bool hasStaffs() {
|
||||
return hasSysAdmin() ||
|
||||
hasAdmin() ||
|
||||
(privileges != null ? privileges.contains('s') : false);
|
||||
}
|
||||
|
||||
bool hasSupport() {
|
||||
return hasSysAdmin() ||
|
||||
hasAdmin() ||
|
||||
(privileges != null ? privileges.contains('sp') : false);
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'User{name: $name, phoneNumber: $phoneNumber,hasSignup:$hasSignup}';
|
||||
return 'User{name: $name, phoneNumber: $phoneNumber,status:$status}';
|
||||
}
|
||||
}
|
||||
|
||||
3
lib/fcs/common/helpers/const.dart
Normal file
3
lib/fcs/common/helpers/const.dart
Normal file
@@ -0,0 +1,3 @@
|
||||
const userStatusInvited = "invited";
|
||||
const userStatusJoined = "joined";
|
||||
const userStatusRequested = "requested";
|
||||
@@ -1,363 +1,128 @@
|
||||
import 'package:fcs/fcs/common/domain/entities/customer.dart';
|
||||
import 'package:fcs/fcs/common/domain/entities/role.dart';
|
||||
import 'package:fcs/fcs/common/domain/entities/user.dart';
|
||||
import 'package:fcs/fcs/common/localization/app_translations.dart';
|
||||
import 'package:fcs/fcs/common/pages/model/language_model.dart';
|
||||
import 'package:fcs/fcs/common/helpers/theme.dart';
|
||||
import 'package:fcs/fcs/common/pages/customers/model/customer_model.dart';
|
||||
import 'package:fcs/fcs/common/pages/util.dart';
|
||||
import 'package:fcs/fcs/common/pages/widgets/display_text.dart';
|
||||
import 'package:fcs/fcs/common/pages/widgets/local_text.dart';
|
||||
import 'package:fcs/fcs/common/pages/widgets/progress.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:fcs/fcs/common/helpers/theme.dart';
|
||||
|
||||
typedef void FindCallBack();
|
||||
|
||||
class CustomerEditor extends StatefulWidget {
|
||||
final Customer customer;
|
||||
final User customer;
|
||||
const CustomerEditor({this.customer});
|
||||
@override
|
||||
_CustomerEditorState createState() => _CustomerEditorState();
|
||||
}
|
||||
|
||||
class _CustomerEditorState extends State<CustomerEditor> {
|
||||
TextEditingController _name = new TextEditingController();
|
||||
TextEditingController _phone = new TextEditingController();
|
||||
TextEditingController _phoneInput = new TextEditingController();
|
||||
TextEditingController _status = new TextEditingController();
|
||||
|
||||
final _formKey = GlobalKey<FormState>();
|
||||
bool _isLoading = false;
|
||||
String currentBizId;
|
||||
bool isSend = false;
|
||||
User user;
|
||||
User selectedUser;
|
||||
List<Privilege> privileges = [
|
||||
Privilege(name: 'Manage shipment'),
|
||||
Privilege(name: 'Manage pickups'),
|
||||
Privilege(name: 'Manage packages'),
|
||||
Privilege(name: 'Manage deliveries'),
|
||||
Privilege(name: 'Admin')
|
||||
];
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
// privileges = Provider.of<UserModel>(context, listen: false).privileges;
|
||||
if (widget.customer != null) {
|
||||
_name.text = widget.customer.name;
|
||||
_phone.text = widget.customer.phoneNumber;
|
||||
_status.text = widget.customer.status;
|
||||
// privileges.forEach((p) => widget.employee.privilegeIds.contains(p.id)
|
||||
// ? p.isChecked = true
|
||||
// : p.isChecked = false);
|
||||
}
|
||||
}
|
||||
|
||||
List<Widget> showprivilegeList(BuildContext context) {
|
||||
return privileges.map((p) {
|
||||
return new ListTile(
|
||||
title: new Row(
|
||||
children: <Widget>[
|
||||
new Checkbox(
|
||||
value: p.isChecked == null ? false : p.isChecked,
|
||||
activeColor: primaryColor,
|
||||
onChanged: (bool value) {
|
||||
setState(() {
|
||||
p.isChecked = value;
|
||||
});
|
||||
}),
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
new Text(
|
||||
p.name,
|
||||
style: TextStyle(
|
||||
fontSize: 15.0,
|
||||
),
|
||||
),
|
||||
// Container(
|
||||
// width: MediaQuery.of(context).size.width * 0.5,
|
||||
// child: new Text(
|
||||
// userModel.getPrivileges[index].desc,
|
||||
// style:
|
||||
// TextStyle(fontSize: 12.0, color: Colors.grey[600]),
|
||||
// ),
|
||||
// ),
|
||||
],
|
||||
),
|
||||
],
|
||||
));
|
||||
}).toList();
|
||||
}
|
||||
|
||||
Widget phoneInputbox(BuildContext context, FindCallBack findCallBack) {
|
||||
var languageModel = Provider.of<LanguageModel>(context);
|
||||
return Container(
|
||||
padding: EdgeInsets.only(top: 10),
|
||||
child: Stack(
|
||||
alignment: const Alignment(1.2, 1.0),
|
||||
children: <Widget>[
|
||||
TextFormField(
|
||||
controller: _phoneInput,
|
||||
autofocus: false,
|
||||
cursorColor: primaryColor,
|
||||
keyboardType: TextInputType.phone,
|
||||
style: textStyle,
|
||||
decoration: new InputDecoration(
|
||||
labelText: AppTranslations.of(context).text('employee.phone'),
|
||||
labelStyle: languageModel.isEng ? labelStyle : labelStyleMM,
|
||||
icon: Icon(
|
||||
Icons.phone,
|
||||
color: primaryColor,
|
||||
),
|
||||
enabledBorder: UnderlineInputBorder(
|
||||
borderSide: BorderSide(color: primaryColor, width: 1.0)),
|
||||
focusedBorder: UnderlineInputBorder(
|
||||
borderSide: BorderSide(color: primaryColor, width: 1.0)),
|
||||
),
|
||||
),
|
||||
new FlatButton(
|
||||
onPressed: () {
|
||||
this.isSend = true;
|
||||
findCallBack();
|
||||
},
|
||||
child: new Icon(
|
||||
Icons.search,
|
||||
size: 25,
|
||||
))
|
||||
],
|
||||
));
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final namebox = TextFormField(
|
||||
controller: _name,
|
||||
autofocus: false,
|
||||
readOnly: true,
|
||||
cursorColor: primaryColor,
|
||||
decoration: new InputDecoration(
|
||||
border: InputBorder.none,
|
||||
focusedBorder: InputBorder.none,
|
||||
icon: Icon(
|
||||
Icons.person,
|
||||
color: primaryColor,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
final displayPhoneNo = TextFormField(
|
||||
controller: _phone,
|
||||
autofocus: false,
|
||||
readOnly: true,
|
||||
cursorColor: primaryColor,
|
||||
decoration: new InputDecoration(
|
||||
border: InputBorder.none,
|
||||
focusedBorder: InputBorder.none,
|
||||
icon: Icon(
|
||||
Icons.phone,
|
||||
color: primaryColor,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
var phoneNumberBox = Row(
|
||||
children: <Widget>[
|
||||
Expanded(child: displayPhoneNo),
|
||||
Expanded(
|
||||
child: InkWell(
|
||||
onTap: () => call(context, _phone.text),
|
||||
child: Icon(
|
||||
Icons.open_in_new,
|
||||
color: Colors.grey,
|
||||
size: 15,
|
||||
),
|
||||
),
|
||||
),
|
||||
child: DisplayText(
|
||||
text: widget.customer.phoneNumber,
|
||||
labelText: getLocalString(context, "customer.phone"),
|
||||
iconData: Icons.phone,
|
||||
)),
|
||||
IconButton(
|
||||
icon: Icon(Icons.open_in_new, color: primaryColor),
|
||||
onPressed: () => call(context, widget.customer.phoneNumber)),
|
||||
],
|
||||
);
|
||||
|
||||
final statusbox = TextFormField(
|
||||
controller: _status,
|
||||
autofocus: false,
|
||||
readOnly: true,
|
||||
cursorColor: primaryColor,
|
||||
decoration: new InputDecoration(
|
||||
border: InputBorder.none,
|
||||
focusedBorder: InputBorder.none,
|
||||
icon: Icon(
|
||||
Icons.av_timer,
|
||||
color: primaryColor,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
final updateButton = Container(
|
||||
padding: EdgeInsets.only(top: 40),
|
||||
child: Container(
|
||||
height: 45.0,
|
||||
decoration: BoxDecoration(
|
||||
color: primaryColor,
|
||||
shape: BoxShape.rectangle,
|
||||
),
|
||||
child: ButtonTheme(
|
||||
minWidth: 900.0,
|
||||
height: 100.0,
|
||||
child: FlatButton(
|
||||
onPressed: () {},
|
||||
child: LocalText(
|
||||
context,
|
||||
'customer.update',
|
||||
color: Colors.white,
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
final addButton = Container(
|
||||
padding: EdgeInsets.only(top: 40),
|
||||
child: Container(
|
||||
height: 45.0,
|
||||
decoration: BoxDecoration(
|
||||
color: primaryColor,
|
||||
shape: BoxShape.rectangle,
|
||||
),
|
||||
child: ButtonTheme(
|
||||
minWidth: 900.0,
|
||||
height: 100.0,
|
||||
child: FlatButton(
|
||||
onPressed: () {},
|
||||
child: LocalText(
|
||||
context,
|
||||
'customer.add',
|
||||
color: Colors.white,
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
return LocalProgress(
|
||||
inAsyncCall: _isLoading,
|
||||
child: Scaffold(
|
||||
appBar: AppBar(
|
||||
centerTitle: true,
|
||||
leading: new IconButton(
|
||||
icon: new Icon(Icons.close),
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
child: SafeArea(
|
||||
child: Scaffold(
|
||||
appBar: AppBar(
|
||||
backgroundColor: Colors.white,
|
||||
shadowColor: Colors.transparent,
|
||||
centerTitle: true,
|
||||
leading: new IconButton(
|
||||
icon: new Icon(
|
||||
Icons.close,
|
||||
color: primaryColor,
|
||||
size: 30,
|
||||
),
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
),
|
||||
title: Text(
|
||||
widget.customer.name,
|
||||
style: TextStyle(
|
||||
fontSize: 20,
|
||||
color: primaryColor,
|
||||
),
|
||||
),
|
||||
),
|
||||
backgroundColor: primaryColor,
|
||||
title: LocalText(
|
||||
context,
|
||||
"customer.form.title",
|
||||
fontSize: 20,
|
||||
color: Colors.white,
|
||||
body: Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Column(
|
||||
children: <Widget>[
|
||||
Expanded(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(left: 18.0, right: 18),
|
||||
child: ListView(
|
||||
children: [
|
||||
phoneNumberBox,
|
||||
DisplayText(
|
||||
text: widget.customer.status,
|
||||
labelText:
|
||||
getLocalString(context, "customer.status"),
|
||||
iconData: Icons.add_alarm,
|
||||
),
|
||||
DisplayText(
|
||||
text: widget.customer.fcsID,
|
||||
labelText:
|
||||
getLocalString(context, "customer.fcs.id"),
|
||||
iconData: Icons.account_circle,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
widget.customer.requested
|
||||
? fcsButton(
|
||||
context,
|
||||
getLocalString(
|
||||
context, "customer.invitation.request.confirm"),
|
||||
callack: _add)
|
||||
: Container()
|
||||
],
|
||||
),
|
||||
),
|
||||
// actions: <Widget>[
|
||||
// widget.customer == null || !mainModel.showHistoryBtn()
|
||||
// ? Container()
|
||||
// : IconButton(
|
||||
// icon: Icon(Icons.history),
|
||||
// onPressed: () {
|
||||
// Navigator.push(
|
||||
// context,
|
||||
// MaterialPageRoute(
|
||||
// builder: (context) => DocumentLogPage(
|
||||
// docID: widget.customer.docID)),
|
||||
// );
|
||||
// },
|
||||
// ),
|
||||
// ],
|
||||
),
|
||||
body: ListView(
|
||||
shrinkWrap: true,
|
||||
padding: EdgeInsets.only(left: 24.0, right: 24.0),
|
||||
children: <Widget>[
|
||||
widget.customer == null
|
||||
? phoneInputbox(context, () => _findUser(context))
|
||||
: phoneNumberBox,
|
||||
widget.customer == null
|
||||
? this.isSend ? namebox : Container()
|
||||
: namebox,
|
||||
statusbox,
|
||||
// widget.customer == null ? addButton : updateButton,
|
||||
SizedBox(
|
||||
height: 20,
|
||||
)
|
||||
],
|
||||
),
|
||||
));
|
||||
}
|
||||
|
||||
_add(BuildContext context) async {
|
||||
if (selectedUser == null) return;
|
||||
setState(() {
|
||||
_isLoading = true;
|
||||
_add() async {
|
||||
showConfirmDialog(context, "customer.invitation.request.confirm", () async {
|
||||
setState(() {
|
||||
_isLoading = true;
|
||||
});
|
||||
if (widget.customer == null) return;
|
||||
CustomerModel customerModel =
|
||||
Provider.of<CustomerModel>(context, listen: false);
|
||||
try {
|
||||
await customerModel.acceptRequest(widget.customer.id);
|
||||
Navigator.pop(context);
|
||||
} catch (e) {
|
||||
showMsgDialog(context, "Error", e.toString());
|
||||
} finally {
|
||||
setState(() {
|
||||
_isLoading = false;
|
||||
});
|
||||
}
|
||||
});
|
||||
// var employeeModel = Provider.of<EmployeeModel>(context);
|
||||
// try {
|
||||
// await employeeModel.updatePrivileges(
|
||||
// this.selectedUser.docID, privilegesIDs());
|
||||
// Navigator.pop(context);
|
||||
// } catch (e) {
|
||||
// showMsgDialog(context, "Error", e.toString());
|
||||
// } finally {
|
||||
// setState(() {
|
||||
// _isLoading = false;
|
||||
// });
|
||||
// }
|
||||
}
|
||||
|
||||
List<String> privilegesIDs() {
|
||||
return this.privileges.where((p) => p.isChecked).map((p) => p.id).toList();
|
||||
}
|
||||
|
||||
_save() async {
|
||||
setState(() {
|
||||
_isLoading = true;
|
||||
});
|
||||
if (widget.customer == null) return;
|
||||
// var employeeModel = Provider.of<EmployeeModel>(context);
|
||||
// try {
|
||||
// await employeeModel.updatePrivileges(
|
||||
// widget.customer.docID, privilegesIDs());
|
||||
// Navigator.pop(context);
|
||||
// } catch (e) {
|
||||
// showMsgDialog(context, "Error", e.toString());
|
||||
// } finally {
|
||||
// setState(() {
|
||||
// _isLoading = false;
|
||||
// });
|
||||
// }
|
||||
}
|
||||
|
||||
_findUser(BuildContext context) async {
|
||||
// var userModel = Provider.of<UserModel>(context);
|
||||
// setState(() {
|
||||
// _isLoading = true;
|
||||
// });
|
||||
// try {
|
||||
// selectedUser = await userModel.findUser(_phoneInput.text);
|
||||
// setState(() {
|
||||
// isSend = true;
|
||||
// _name.text = selectedUser.name;
|
||||
// if (selectedUser.privilegeIds != null) {
|
||||
// privileges.forEach((p) => selectedUser.privilegeIds.contains(p.id)
|
||||
// ? p.isChecked = true
|
||||
// : p.isChecked = false);
|
||||
// }
|
||||
// });
|
||||
// } catch (e) {
|
||||
// showMsgDialog(context, "Error", e.toString());
|
||||
// } finally {
|
||||
// setState(() {
|
||||
// _isLoading = false;
|
||||
// });
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,20 +1,18 @@
|
||||
import 'package:fcs/fcs/common/domain/entities/customer.dart';
|
||||
import 'package:fcs/fcs/common/domain/entities/user.dart';
|
||||
import 'package:fcs/fcs/common/localization/app_translations.dart';
|
||||
import 'package:fcs/fcs/common/pages/customers/invitation_page.dart';
|
||||
import 'package:fcs/fcs/common/helpers/theme.dart';
|
||||
import 'package:fcs/fcs/common/pages/customers/customer_editor.dart';
|
||||
import 'package:fcs/fcs/common/pages/customers/invitation_list.dart';
|
||||
import 'package:fcs/fcs/common/pages/customers/model/customer_model.dart';
|
||||
import 'package:fcs/fcs/common/pages/util.dart';
|
||||
import 'package:fcs/fcs/common/pages/widgets/bottom_up_page_route.dart';
|
||||
import 'package:fcs/fcs/common/pages/widgets/local_text.dart';
|
||||
import 'package:fcs/widget/progress.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_icons/flutter_icons.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:fcs/fcs/common/helpers/theme.dart';
|
||||
import 'package:fcs/widget/progress.dart';
|
||||
|
||||
import 'customer_editor.dart';
|
||||
import 'invitation_editor.dart';
|
||||
|
||||
class CustomerList extends StatefulWidget {
|
||||
@override
|
||||
@@ -40,14 +38,14 @@ class _CustomerListState extends State<CustomerList> {
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
),
|
||||
actions: <Widget>[
|
||||
IconButton(
|
||||
icon: Icon(
|
||||
Icons.search,
|
||||
color: Colors.white,
|
||||
),
|
||||
iconSize: 30,
|
||||
onPressed: () => {},
|
||||
),
|
||||
// IconButton(
|
||||
// icon: Icon(
|
||||
// Icons.search,
|
||||
// color: Colors.white,
|
||||
// ),
|
||||
// iconSize: 30,
|
||||
// onPressed: () => {},
|
||||
// ),
|
||||
],
|
||||
backgroundColor: primaryColor,
|
||||
title: LocalText(
|
||||
@@ -57,86 +55,114 @@ class _CustomerListState extends State<CustomerList> {
|
||||
fontSize: 20,
|
||||
),
|
||||
),
|
||||
floatingActionButton: FloatingActionButton.extended(
|
||||
onPressed: () {
|
||||
Navigator.of(context).push(BottomUpPageRoute(InvitationPage()));
|
||||
},
|
||||
icon: Icon(Icons.add),
|
||||
label: Text(AppTranslations.of(context).text("customer.invite")),
|
||||
backgroundColor: primaryColor,
|
||||
),
|
||||
body: new ListView.separated(
|
||||
separatorBuilder: (context, index) => Divider(
|
||||
color: Colors.black,
|
||||
),
|
||||
scrollDirection: Axis.vertical,
|
||||
padding: EdgeInsets.only(left: 15, right: 15, top: 15),
|
||||
shrinkWrap: true,
|
||||
itemCount: customerModel.customers.length,
|
||||
itemBuilder: (BuildContext context, int index) {
|
||||
Customer customer = customerModel.customers[index];
|
||||
return Stack(
|
||||
children: <Widget>[
|
||||
InkWell(
|
||||
onTap: () {
|
||||
Navigator.of(context).push(
|
||||
BottomUpPageRoute(CustomerEditor(customer: customer)));
|
||||
},
|
||||
child: Row(
|
||||
children: <Widget>[
|
||||
Expanded(
|
||||
child: new Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 10.0),
|
||||
child: new Row(
|
||||
children: <Widget>[
|
||||
new Padding(
|
||||
padding: new EdgeInsets.symmetric(
|
||||
horizontal: 32.0 - dotSize / 2),
|
||||
child: Icon(
|
||||
Feather.user,
|
||||
color: primaryColor,
|
||||
size: 40,
|
||||
),
|
||||
),
|
||||
new Expanded(
|
||||
child: new Column(
|
||||
crossAxisAlignment:
|
||||
CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
new Text(
|
||||
customer.name,
|
||||
style: new TextStyle(
|
||||
fontSize: 15.0,
|
||||
color: primaryColor),
|
||||
),
|
||||
Padding(
|
||||
padding:
|
||||
const EdgeInsets.only(top: 8.0),
|
||||
child: new Text(
|
||||
customer.phoneNumber,
|
||||
style: new TextStyle(
|
||||
fontSize: 15.0,
|
||||
color: Colors.grey),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(right: 10),
|
||||
child: getStatus(customer.status),
|
||||
),
|
||||
],
|
||||
body: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.end,
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 3, right: 5),
|
||||
child: InkWell(
|
||||
onTap: _invitations,
|
||||
child: Container(
|
||||
color: primaryColor,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(5.0),
|
||||
child: Text(
|
||||
"Invitations",
|
||||
style: TextStyle(color: Colors.white),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}),
|
||||
),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: ListView.separated(
|
||||
separatorBuilder: (context, index) => Divider(
|
||||
color: Colors.black,
|
||||
),
|
||||
scrollDirection: Axis.vertical,
|
||||
padding: EdgeInsets.only(left: 15, right: 15),
|
||||
shrinkWrap: true,
|
||||
itemCount: customerModel.customers.length,
|
||||
itemBuilder: (BuildContext context, int index) {
|
||||
User customer = customerModel.customers[index];
|
||||
return _item(customer);
|
||||
}),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _item(User customer) {
|
||||
return Stack(
|
||||
children: <Widget>[
|
||||
InkWell(
|
||||
onTap: () => _select(customer),
|
||||
child: Row(
|
||||
children: <Widget>[
|
||||
Expanded(
|
||||
child: new Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 10.0),
|
||||
child: new Row(
|
||||
children: <Widget>[
|
||||
new Padding(
|
||||
padding: new EdgeInsets.symmetric(
|
||||
horizontal: 32.0 - dotSize / 2),
|
||||
child: Icon(
|
||||
Feather.user,
|
||||
color: primaryColor,
|
||||
size: 40,
|
||||
),
|
||||
),
|
||||
new Expanded(
|
||||
child: new Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
new Text(
|
||||
customer.name,
|
||||
style: new TextStyle(
|
||||
fontSize: 15.0, color: primaryColor),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 8.0),
|
||||
child: new Text(
|
||||
customer.phoneNumber,
|
||||
style: new TextStyle(
|
||||
fontSize: 15.0, color: Colors.grey),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(right: 10),
|
||||
child: _status(customer.status),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget _status(String status) {
|
||||
return Text(
|
||||
status == "requested" ? status : "",
|
||||
style: TextStyle(color: primaryColor, fontSize: 14),
|
||||
);
|
||||
}
|
||||
|
||||
_select(User customer) {
|
||||
Navigator.of(context)
|
||||
.push(BottomUpPageRoute(CustomerEditor(customer: customer)));
|
||||
}
|
||||
|
||||
_invitations() {
|
||||
Navigator.of(context).push(BottomUpPageRoute(InvitationList()));
|
||||
}
|
||||
}
|
||||
|
||||
159
lib/fcs/common/pages/customers/invitation_detail.dart
Normal file
159
lib/fcs/common/pages/customers/invitation_detail.dart
Normal file
@@ -0,0 +1,159 @@
|
||||
import 'package:country_code_picker/country_code_picker.dart';
|
||||
import 'package:fcs/fcs/common/helpers/theme.dart';
|
||||
import 'package:fcs/fcs/common/localization/app_translations.dart';
|
||||
import 'package:fcs/fcs/common/pages/customers/model/customer_model.dart';
|
||||
import 'package:fcs/fcs/common/pages/util.dart';
|
||||
import 'package:fcs/widget/progress.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class InvitationDetail extends StatefulWidget {
|
||||
@override
|
||||
_InvitationDetailState createState() => _InvitationDetailState();
|
||||
}
|
||||
|
||||
class _InvitationDetailState extends State<InvitationDetail> {
|
||||
TextEditingController _nameController = new TextEditingController();
|
||||
TextEditingController _phoneController = new TextEditingController();
|
||||
|
||||
bool _isLoading = false;
|
||||
String dialCode;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
dialCode = "+95";
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return LocalProgress(
|
||||
inAsyncCall: _isLoading,
|
||||
child: Scaffold(
|
||||
appBar: AppBar(
|
||||
centerTitle: true,
|
||||
leading: new IconButton(
|
||||
icon: new Icon(
|
||||
Icons.close,
|
||||
),
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
),
|
||||
backgroundColor: primaryColor,
|
||||
title: Text(AppTranslations.of(context).text("invitation.new")),
|
||||
),
|
||||
body: Container(
|
||||
padding: EdgeInsets.all(18),
|
||||
child: Column(
|
||||
children: <Widget>[
|
||||
Expanded(
|
||||
child: ListView(
|
||||
children: <Widget>[
|
||||
fcsInput("Name", Icons.person,
|
||||
controller: _nameController, autoFocus: true),
|
||||
SizedBox(height: 10),
|
||||
Row(
|
||||
children: <Widget>[
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Icon(
|
||||
Icons.phone,
|
||||
color: primaryColor,
|
||||
),
|
||||
),
|
||||
Container(
|
||||
decoration: BoxDecoration(
|
||||
border:
|
||||
Border.all(color: Colors.grey[400], width: 1),
|
||||
borderRadius:
|
||||
BorderRadius.all(Radius.circular(12.0))),
|
||||
child: CountryCodePicker(
|
||||
onChanged: _countryChange,
|
||||
initialSelection: dialCode,
|
||||
countryFilter: ['+95', '+1'],
|
||||
showCountryOnly: false,
|
||||
showOnlyCountryWhenClosed: false,
|
||||
alignLeft: false,
|
||||
textStyle: TextStyle(
|
||||
fontSize: 16,
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
width: 10,
|
||||
),
|
||||
Flexible(
|
||||
child: Container(
|
||||
padding: EdgeInsets.only(top: 10, bottom: 10),
|
||||
child: TextFormField(
|
||||
controller: _phoneController,
|
||||
cursorColor: primaryColor,
|
||||
textAlign: TextAlign.left,
|
||||
keyboardType: TextInputType.phone,
|
||||
style: TextStyle(
|
||||
fontSize: 18,
|
||||
),
|
||||
decoration: InputDecoration(
|
||||
fillColor: Colors.white,
|
||||
labelText: "Phone number",
|
||||
labelStyle:
|
||||
TextStyle(fontSize: 16, color: Colors.grey),
|
||||
filled: true,
|
||||
focusedBorder: UnderlineInputBorder(
|
||||
borderSide: BorderSide(
|
||||
color: Colors.grey, width: 1.0)),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
fcsButton(context, "Invite", callack: _invite),
|
||||
SizedBox(height: 10)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
_countryChange(CountryCode countryCode) {
|
||||
setState(() {
|
||||
dialCode = countryCode.dialCode;
|
||||
});
|
||||
}
|
||||
|
||||
_invite() async {
|
||||
String userName = _nameController.text;
|
||||
String phoneNumber = dialCode + _phoneController.text;
|
||||
if (userName == null ||
|
||||
userName == "" ||
|
||||
phoneNumber == null ||
|
||||
phoneNumber == "") {
|
||||
showMsgDialog(context, "Error", "Invalid name or phone number");
|
||||
return;
|
||||
}
|
||||
setState(() {
|
||||
_isLoading = true;
|
||||
});
|
||||
try {
|
||||
CustomerModel customerModel =
|
||||
Provider.of<CustomerModel>(context, listen: false);
|
||||
await customerModel.inviteUser(userName, phoneNumber);
|
||||
Navigator.pop(context);
|
||||
} catch (e) {
|
||||
showMsgDialog(context, "Error", e.toString());
|
||||
} finally {
|
||||
setState(() {
|
||||
_isLoading = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
105
lib/fcs/common/pages/customers/invitation_editor.dart
Normal file
105
lib/fcs/common/pages/customers/invitation_editor.dart
Normal file
@@ -0,0 +1,105 @@
|
||||
import 'package:fcs/fcs/common/domain/entities/customer.dart';
|
||||
import 'package:fcs/fcs/common/domain/entities/role.dart';
|
||||
import 'package:fcs/fcs/common/domain/entities/user.dart';
|
||||
import 'package:fcs/fcs/common/localization/app_translations.dart';
|
||||
import 'package:fcs/fcs/common/pages/customers/model/customer_model.dart';
|
||||
import 'package:fcs/fcs/common/pages/model/language_model.dart';
|
||||
import 'package:fcs/fcs/common/pages/util.dart';
|
||||
import 'package:fcs/fcs/common/pages/widgets/display_text.dart';
|
||||
import 'package:fcs/fcs/common/pages/widgets/local_text.dart';
|
||||
import 'package:fcs/fcs/common/pages/widgets/progress.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:fcs/fcs/common/helpers/theme.dart';
|
||||
|
||||
typedef void FindCallBack();
|
||||
|
||||
class InvitationEditor extends StatefulWidget {
|
||||
final User customer;
|
||||
const InvitationEditor({this.customer});
|
||||
@override
|
||||
_InvitationEditorState createState() => _InvitationEditorState();
|
||||
}
|
||||
|
||||
class _InvitationEditorState extends State<InvitationEditor> {
|
||||
bool _isLoading = false;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
var phoneNumberBox = Row(
|
||||
children: <Widget>[
|
||||
Expanded(
|
||||
child: DisplayText(
|
||||
text: widget.customer.phoneNumber,
|
||||
labelText: getLocalString(context, "customer.phone"),
|
||||
iconData: Icons.phone,
|
||||
)),
|
||||
IconButton(
|
||||
icon: Icon(Icons.open_in_new, color: primaryColor),
|
||||
onPressed: () => call(context, widget.customer.phoneNumber)),
|
||||
],
|
||||
);
|
||||
|
||||
return LocalProgress(
|
||||
inAsyncCall: _isLoading,
|
||||
child: Scaffold(
|
||||
appBar: AppBar(
|
||||
backgroundColor: Colors.white,
|
||||
shadowColor: Colors.transparent,
|
||||
centerTitle: true,
|
||||
leading: new IconButton(
|
||||
icon: new Icon(
|
||||
Icons.close,
|
||||
color: primaryColor,
|
||||
size: 30,
|
||||
),
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
),
|
||||
title: Text(
|
||||
widget.customer.name,
|
||||
style: TextStyle(fontSize: 20, color: primaryColor),
|
||||
),
|
||||
),
|
||||
body: Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Column(
|
||||
children: <Widget>[
|
||||
Expanded(
|
||||
child: ListView(
|
||||
children: [phoneNumberBox],
|
||||
),
|
||||
),
|
||||
fcsButton(context, getLocalString(context, "btn.delete"),
|
||||
callack: _delete)
|
||||
],
|
||||
),
|
||||
),
|
||||
));
|
||||
}
|
||||
|
||||
_delete() async {
|
||||
showConfirmDialog(context, "invitation.confirm.delete", () async {
|
||||
setState(() {
|
||||
_isLoading = true;
|
||||
});
|
||||
if (widget.customer == null) return;
|
||||
CustomerModel customerModel =
|
||||
Provider.of<CustomerModel>(context, listen: false);
|
||||
try {
|
||||
await customerModel.deleteInvite(widget.customer.phoneNumber);
|
||||
Navigator.pop(context);
|
||||
} catch (e) {
|
||||
showMsgDialog(context, "Error", e.toString());
|
||||
} finally {
|
||||
setState(() {
|
||||
_isLoading = false;
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
148
lib/fcs/common/pages/customers/invitation_list.dart
Normal file
148
lib/fcs/common/pages/customers/invitation_list.dart
Normal file
@@ -0,0 +1,148 @@
|
||||
import 'package:fcs/fcs/common/pages/model/main_model.dart';
|
||||
import 'package:share/share.dart';
|
||||
import 'package:fcs/fcs/common/domain/entities/user.dart';
|
||||
import 'package:fcs/fcs/common/localization/app_translations.dart';
|
||||
import 'package:fcs/fcs/common/pages/customers/invitation_detail.dart';
|
||||
import 'package:fcs/fcs/common/pages/customers/model/customer_model.dart';
|
||||
import 'package:fcs/fcs/common/pages/util.dart';
|
||||
import 'package:fcs/fcs/common/pages/widgets/bottom_up_page_route.dart';
|
||||
import 'package:fcs/fcs/common/pages/widgets/local_text.dart';
|
||||
import 'package:fcs/fcs/common/pages/widgets/progress.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_icons/flutter_icons.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:fcs/fcs/common/helpers/theme.dart';
|
||||
|
||||
import 'invitation_editor.dart';
|
||||
|
||||
class InvitationList extends StatefulWidget {
|
||||
@override
|
||||
_InvitationListState createState() => _InvitationListState();
|
||||
}
|
||||
|
||||
class _InvitationListState extends State<InvitationList> {
|
||||
var dateFormatter = new DateFormat('dd MMM yyyy - hh:mm:ss a');
|
||||
final double dotSize = 15.0;
|
||||
bool _isLoading = false;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
var customerModel = Provider.of<CustomerModel>(context);
|
||||
|
||||
return LocalProgress(
|
||||
inAsyncCall: _isLoading,
|
||||
child: Scaffold(
|
||||
appBar: AppBar(
|
||||
centerTitle: true,
|
||||
leading: new IconButton(
|
||||
icon: new Icon(Icons.close),
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
),
|
||||
actions: <Widget>[],
|
||||
backgroundColor: primaryColor,
|
||||
title: LocalText(
|
||||
context,
|
||||
'invitation.list',
|
||||
color: Colors.white,
|
||||
fontSize: 20,
|
||||
),
|
||||
),
|
||||
floatingActionButton: FloatingActionButton.extended(
|
||||
onPressed: () {
|
||||
Navigator.of(context).push(BottomUpPageRoute(InvitationDetail()));
|
||||
},
|
||||
icon: Icon(Icons.add),
|
||||
label: Text(AppTranslations.of(context).text("invitation.new")),
|
||||
backgroundColor: primaryColor,
|
||||
),
|
||||
body: new ListView.separated(
|
||||
separatorBuilder: (context, index) => Divider(
|
||||
color: Colors.black,
|
||||
),
|
||||
scrollDirection: Axis.vertical,
|
||||
padding: EdgeInsets.only(left: 15, right: 15, top: 15),
|
||||
shrinkWrap: true,
|
||||
itemCount: customerModel.invitations.length,
|
||||
itemBuilder: (BuildContext context, int index) {
|
||||
User customer = customerModel.invitations[index];
|
||||
return _item(customer);
|
||||
}),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _item(User customer) {
|
||||
return Stack(
|
||||
children: <Widget>[
|
||||
InkWell(
|
||||
onTap: () {
|
||||
Navigator.of(context)
|
||||
.push(BottomUpPageRoute(InvitationEditor(customer: customer)));
|
||||
},
|
||||
child: Row(
|
||||
children: <Widget>[
|
||||
Expanded(
|
||||
child: new Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 10.0),
|
||||
child: new Row(
|
||||
children: <Widget>[
|
||||
new Padding(
|
||||
padding: new EdgeInsets.symmetric(
|
||||
horizontal: 32.0 - dotSize / 2),
|
||||
child: Icon(
|
||||
Feather.user,
|
||||
color: primaryColor,
|
||||
size: 40,
|
||||
),
|
||||
),
|
||||
new Expanded(
|
||||
child: new Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
new Text(
|
||||
customer.name,
|
||||
style: new TextStyle(
|
||||
fontSize: 15.0, color: primaryColor),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 8.0),
|
||||
child: new Text(
|
||||
customer.phoneNumber,
|
||||
style: new TextStyle(
|
||||
fontSize: 15.0, color: Colors.grey),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
FlatButton(
|
||||
onPressed: () => _share(customer),
|
||||
child: Row(
|
||||
children: [
|
||||
Text("Share"),
|
||||
Icon(Icons.share),
|
||||
],
|
||||
)),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
_share(User user) async {
|
||||
MainModel mainModel = Provider.of<MainModel>(context, listen: false);
|
||||
String appUrl = mainModel.setting.appUrl;
|
||||
final RenderBox box = context.findRenderObject();
|
||||
await Share.share(
|
||||
user.share + "\n Please join us from this link:\n $appUrl",
|
||||
subject: "Invitation to FCS App",
|
||||
sharePositionOrigin: box.localToGlobal(Offset.zero) & box.size);
|
||||
}
|
||||
}
|
||||
@@ -1,67 +0,0 @@
|
||||
import 'package:fcs/fcs/common/helpers/theme.dart';
|
||||
import 'package:fcs/fcs/common/localization/app_translations.dart';
|
||||
import 'package:fcs/fcs/common/pages/util.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:fcs/widget/progress.dart';
|
||||
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||
|
||||
class InvitationPage extends StatefulWidget {
|
||||
@override
|
||||
_InvitationPageState createState() => _InvitationPageState();
|
||||
}
|
||||
|
||||
class _InvitationPageState extends State<InvitationPage> {
|
||||
TextEditingController _nameController = new TextEditingController();
|
||||
TextEditingController _phoneController = new TextEditingController();
|
||||
|
||||
bool _isLoading = false;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return LocalProgress(
|
||||
inAsyncCall: _isLoading,
|
||||
child: Scaffold(
|
||||
appBar: AppBar(
|
||||
centerTitle: true,
|
||||
leading: new IconButton(
|
||||
icon: new Icon(
|
||||
Icons.close,
|
||||
),
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
),
|
||||
backgroundColor: primaryColor,
|
||||
title: Text(AppTranslations.of(context).text("customer.form.title")),
|
||||
),
|
||||
body: Container(
|
||||
padding: EdgeInsets.all(18),
|
||||
child: Column(
|
||||
children: <Widget>[
|
||||
Expanded(
|
||||
child: ListView(
|
||||
children: <Widget>[
|
||||
fcsInput("Name", Icons.person, controller: _nameController),
|
||||
fcsInput("Phone Number", Icons.phone,
|
||||
controller: _phoneController),
|
||||
SizedBox(height: 30),
|
||||
],
|
||||
),
|
||||
),
|
||||
fcsButton(context, "Invite", callack: () {}),
|
||||
SizedBox(height: 10)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,26 +1,20 @@
|
||||
import 'package:fcs/fcs/common/domain/entities/customer.dart';
|
||||
import 'package:cloud_firestore/cloud_firestore.dart';
|
||||
import 'package:fcs/fcs/common/domain/constants.dart';
|
||||
import 'package:fcs/fcs/common/domain/entities/user.dart';
|
||||
import 'package:fcs/fcs/common/pages/model/base_model.dart';
|
||||
import 'package:fcs/fcs/common/services/services.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
|
||||
|
||||
class CustomerModel extends BaseModel {
|
||||
final log = Logger('CustomerModel');
|
||||
|
||||
List<Customer> customers = [
|
||||
Customer(
|
||||
name: 'Ko Nyi',
|
||||
phoneNumber: '+95 9 717273634',
|
||||
status: 'Invited'
|
||||
),
|
||||
Customer(name: 'Ko Phyu', phoneNumber: '+1 (939) 382-3844',status: 'Signin'),
|
||||
Customer(name: 'Ko Ye', phoneNumber: '+95 9 983734783', status: 'Invited'),
|
||||
];
|
||||
|
||||
|
||||
List<User> customers = [];
|
||||
List<User> invitations = [];
|
||||
|
||||
void initUser(user) async {
|
||||
super.initUser(user);
|
||||
// _loadCustomer();
|
||||
_loadCustomer();
|
||||
_loadInvitations();
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -28,31 +22,64 @@ class CustomerModel extends BaseModel {
|
||||
customers = [];
|
||||
}
|
||||
|
||||
// Future<void> _loadCustomer() async {
|
||||
// if (!user.isOwnerAndAbove() && !user.hasAccount()) {
|
||||
// return;
|
||||
// }
|
||||
Future<void> inviteUser(String userName, String phoneNumber) {
|
||||
return Services.instance.userService.inviteUser(userName, phoneNumber);
|
||||
}
|
||||
|
||||
// try {
|
||||
// Firestore.instance
|
||||
// .collection("/$biz_collection/${setting.okEnergyId}/$user_collection")
|
||||
// .where("is_employee", isEqualTo: true)
|
||||
// .snapshots()
|
||||
// .listen((QuerySnapshot snapshot) {
|
||||
// customers.clear();
|
||||
// customers = snapshot.documents.map((documentSnapshot) {
|
||||
// var user =
|
||||
// User.fromMap(documentSnapshot.data, documentSnapshot.documentID);
|
||||
// return user;
|
||||
// }).toList();
|
||||
// notifyListeners();
|
||||
// }).onError((e) {
|
||||
// log.warning("Error! $e");
|
||||
// });
|
||||
// } catch (e) {
|
||||
// log.warning("Error!! $e");
|
||||
// }
|
||||
// }
|
||||
Future<void> deleteInvite(String phoneNumber) {
|
||||
return Services.instance.userService.deleteInvite(phoneNumber);
|
||||
}
|
||||
|
||||
Future<void> acceptRequest(String userID) {
|
||||
return Services.instance.userService.acceptRequest(userID);
|
||||
}
|
||||
|
||||
Future<void> _loadCustomer() async {
|
||||
if (user == null || !user.hasCustomers()) return;
|
||||
|
||||
try {
|
||||
Firestore.instance
|
||||
.collection("/$user_collection")
|
||||
.where("is_sys_admin", isEqualTo: false)
|
||||
.snapshots()
|
||||
.listen((QuerySnapshot snapshot) {
|
||||
customers.clear();
|
||||
customers = snapshot.documents.map((documentSnapshot) {
|
||||
var user =
|
||||
User.fromMap(documentSnapshot.data, documentSnapshot.documentID);
|
||||
return user;
|
||||
}).toList();
|
||||
notifyListeners();
|
||||
}).onError((e) {
|
||||
log.warning("Error! $e");
|
||||
});
|
||||
} catch (e) {
|
||||
log.warning("Error!! $e");
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _loadInvitations() async {
|
||||
if (user == null || !user.hasCustomers()) return;
|
||||
|
||||
try {
|
||||
Firestore.instance
|
||||
.collection("/$invitations_collection")
|
||||
.snapshots()
|
||||
.listen((QuerySnapshot snapshot) {
|
||||
invitations.clear();
|
||||
invitations = snapshot.documents.map((documentSnapshot) {
|
||||
var user =
|
||||
User.fromMap(documentSnapshot.data, documentSnapshot.documentID);
|
||||
return user;
|
||||
}).toList();
|
||||
notifyListeners();
|
||||
}).onError((e) {
|
||||
log.warning("Error! $e");
|
||||
});
|
||||
} catch (e) {
|
||||
log.warning("Error!! $e");
|
||||
}
|
||||
}
|
||||
|
||||
// Future<void> updatePrivileges(String userID, List<String> privileges) async {
|
||||
// try {
|
||||
|
||||
@@ -12,12 +12,12 @@ import 'package:provider/provider.dart';
|
||||
|
||||
import 'model/faq_model.dart';
|
||||
|
||||
class FAQPage extends StatefulWidget {
|
||||
class FAQListPage extends StatefulWidget {
|
||||
@override
|
||||
_FAQPageState createState() => _FAQPageState();
|
||||
_FAQListPageState createState() => _FAQListPageState();
|
||||
}
|
||||
|
||||
class _FAQPageState extends State<FAQPage> {
|
||||
class _FAQListPageState extends State<FAQListPage> {
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
@@ -51,18 +51,20 @@ class _FAQPageState extends State<FAQPage> {
|
||||
color: Colors.white,
|
||||
)),
|
||||
),
|
||||
actions:isEditable? [
|
||||
IconButton(
|
||||
onPressed: () =>
|
||||
Navigator.of(context).push<void>(CupertinoPageRoute(
|
||||
builder: (context) => FAQEditor(),
|
||||
)),
|
||||
icon: Icon(
|
||||
CupertinoIcons.add,
|
||||
color: Colors.white,
|
||||
size: 35,
|
||||
))
|
||||
]:[],
|
||||
actions: isEditable
|
||||
? [
|
||||
IconButton(
|
||||
onPressed: () =>
|
||||
Navigator.of(context).push<void>(CupertinoPageRoute(
|
||||
builder: (context) => FAQEditor(),
|
||||
)),
|
||||
icon: Icon(
|
||||
CupertinoIcons.add,
|
||||
color: Colors.white,
|
||||
size: 35,
|
||||
))
|
||||
]
|
||||
: [],
|
||||
),
|
||||
SliverList(
|
||||
delegate: SliverChildBuilderDelegate(
|
||||
@@ -92,15 +94,15 @@ class _FAQPageState extends State<FAQPage> {
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Flexible(
|
||||
child: TextLocalStyle(
|
||||
child: TextLocalStyle(
|
||||
context,
|
||||
faq.question(isEng),
|
||||
fontSize: 18,
|
||||
fontSize: 16,
|
||||
),
|
||||
),
|
||||
// Spacer(),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(left:18.0),
|
||||
padding: const EdgeInsets.only(left: 18.0),
|
||||
child: Icon(
|
||||
CupertinoIcons.right_chevron,
|
||||
color: primaryColor,
|
||||
@@ -1,8 +1,11 @@
|
||||
import 'package:fcs/fcs/common/domain/entities/user.dart';
|
||||
import 'package:fcs/fcs/common/localization/transalation.dart';
|
||||
import 'package:fcs/fcs/common/pages/customers/customer_list.dart';
|
||||
import 'package:fcs/fcs/common/pages/faq/faq_page.dart';
|
||||
import 'package:fcs/fcs/common/pages/faq/faq_list_page.dart';
|
||||
import 'package:fcs/fcs/common/pages/model/language_model.dart';
|
||||
import 'package:fcs/fcs/common/pages/model/main_model.dart';
|
||||
import 'package:fcs/fcs/common/pages/staff/staff_list.dart';
|
||||
import 'package:fcs/fcs/common/pages/util.dart';
|
||||
import 'package:fcs/fcs/common/pages/widgets/action_button.dart';
|
||||
import 'package:fcs/fcs/common/pages/widgets/bottom_widgets.dart';
|
||||
import 'package:fcs/pages/discount_list.dart';
|
||||
@@ -30,9 +33,8 @@ import '../../../pages/fcs_profile_page.dart';
|
||||
import '../../../pages/invoice/invoce_list.dart';
|
||||
import '../../../pages/pickup_list.dart';
|
||||
import '../../../pages/shipment_rates.dart';
|
||||
import '../../../pages/staff_list.dart';
|
||||
import '../helpers/theme.dart';
|
||||
import 'profile_page.dart';
|
||||
import 'profile/profile_page.dart';
|
||||
import 'signin/signin_page.dart';
|
||||
|
||||
final msgLog = Logger('backgroundMessageHandler');
|
||||
@@ -70,6 +72,7 @@ class _HomePageState extends State<HomePage> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
User user = Provider.of<MainModel>(context).user;
|
||||
login = Provider.of<MainModel>(context).isLogin();
|
||||
// var owner =true;// Provider.of<MainModel>(context).isOwner();
|
||||
var customer = Provider.of<MainModel>(context).isCustomer();
|
||||
@@ -78,7 +81,7 @@ class _HomePageState extends State<HomePage> {
|
||||
final faqBtn = _buildBtn("faq.btn",
|
||||
icon: MaterialCommunityIcons.frequently_asked_questions,
|
||||
btnCallback: () => Navigator.of(context).push(CupertinoPageRoute(
|
||||
builder: (context) => FAQPage(),
|
||||
builder: (context) => FAQListPage(),
|
||||
)));
|
||||
|
||||
final packagesBtn = _buildBtn("package.name",
|
||||
@@ -169,22 +172,23 @@ class _HomePageState extends State<HomePage> {
|
||||
|
||||
List<Widget> widgets = [];
|
||||
widgets.add(faqBtn);
|
||||
// customer ? widgets.add(buyingBtn) : "";
|
||||
// customer || owner ? widgets.add(pickUpBtn) : "";
|
||||
!customer ? widgets.add(shipmentBtn) : "";
|
||||
// customer || owner ? widgets.add(notiBtn) : "";
|
||||
// owner ? widgets.add(staffBtn) : "";
|
||||
// owner ? widgets.add(fcsProfileBtn) : "";
|
||||
// widgets.add(shipmentCostBtn);
|
||||
// customer || owner ? widgets.add(packagesBtn) : "";
|
||||
// owner ? widgets.add(boxesBtn) : "";
|
||||
// owner ? widgets.add(deliveryBtn) : "";
|
||||
widgets.add(customersBtn);
|
||||
// customer || owner ? widgets.add(invoicesBtn) : "";
|
||||
// owner ? widgets.add(paymentMethodBtn) : "";
|
||||
// owner ? widgets.add(discountBtn) : "";
|
||||
// widgets.add(termBtn);
|
||||
|
||||
if (user != null) {
|
||||
// customer ? widgets.add(buyingBtn) : "";
|
||||
// customer || owner ? widgets.add(pickUpBtn) : "";
|
||||
// !customer ? widgets.add(shipmentBtn) : "";
|
||||
// customer || owner ? widgets.add(notiBtn) : "";
|
||||
user.hasStaffs() ? widgets.add(staffBtn) : "";
|
||||
// owner ? widgets.add(fcsProfileBtn) : "";
|
||||
// widgets.add(shipmentCostBtn);
|
||||
// customer || owner ? widgets.add(packagesBtn) : "";
|
||||
// owner ? widgets.add(boxesBtn) : "";
|
||||
// owner ? widgets.add(deliveryBtn) : "";
|
||||
user.hasCustomers() ? widgets.add(customersBtn) : "";
|
||||
// customer || owner ? widgets.add(invoicesBtn) : "";
|
||||
// owner ? widgets.add(paymentMethodBtn) : "";
|
||||
// owner ? widgets.add(discountBtn) : "";
|
||||
// widgets.add(termBtn);
|
||||
}
|
||||
return OfflineRedirect(
|
||||
child: FlavorBanner(
|
||||
child: Scaffold(
|
||||
@@ -295,6 +299,16 @@ class _HomePageState extends State<HomePage> {
|
||||
),
|
||||
child: Column(
|
||||
children: <Widget>[
|
||||
user.requested
|
||||
? Container(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Text(
|
||||
getLocalString(
|
||||
context, "home.invitation.request.msg"),
|
||||
style: TextStyle(color: Colors.white70),
|
||||
),
|
||||
)
|
||||
: Container(),
|
||||
Expanded(
|
||||
child: ListView(children: [
|
||||
Wrap(
|
||||
|
||||
@@ -5,6 +5,7 @@ import 'package:fcs/fcs/common/pages/model/language_model.dart';
|
||||
import 'package:fcs/fcs/common/pages/model/main_model.dart';
|
||||
import 'package:fcs/fcs/common/pages/signin/signin_page.dart';
|
||||
import 'package:fcs/fcs/common/pages/widgets/local_text.dart';
|
||||
import 'package:fcs/fcs/common/pages/widgets/progress.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
@@ -28,10 +29,12 @@ class _InitialLanguageSelectionPageState
|
||||
|
||||
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);
|
||||
@@ -48,119 +51,122 @@ class _InitialLanguageSelectionPageState
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return 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],
|
||||
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()),
|
||||
),
|
||||
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),
|
||||
),
|
||||
),
|
||||
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)),
|
||||
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)),
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -179,9 +185,18 @@ class _InitialLanguageSelectionPageState
|
||||
}
|
||||
|
||||
_next() {
|
||||
SharedPref.finishFirstLaunch();
|
||||
bool isLogin = Provider.of<MainModel>(context, listen: false).isLogin();
|
||||
String page = isLogin ? "/home" : "/welcome";
|
||||
Navigator.of(context).pushReplacementNamed(page);
|
||||
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;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,20 +36,21 @@ class MainModel extends ChangeNotifier {
|
||||
});
|
||||
Services.instance.authService.onAuthStatus().listen((event) {
|
||||
this.user = event;
|
||||
_initUser(user);
|
||||
notifyListeners();
|
||||
});
|
||||
}
|
||||
|
||||
bool faqEditable() {
|
||||
return this.user != null && false;
|
||||
return this.user != null && this.user.hasSupport();
|
||||
}
|
||||
|
||||
bool termEditable() {
|
||||
return this.user != null && false;
|
||||
return this.user != null && this.user.hasSupport();
|
||||
}
|
||||
|
||||
bool contactEditable() {
|
||||
return this.user != null && false;
|
||||
return this.user != null && this.user.hasSupport();
|
||||
}
|
||||
|
||||
bool isLogin() {
|
||||
@@ -81,13 +82,13 @@ class MainModel extends ChangeNotifier {
|
||||
models.add(model);
|
||||
}
|
||||
|
||||
// void _initUser(User user) {
|
||||
// models.forEach((m) => m.initUser(user));
|
||||
void _initUser(User user) {
|
||||
models.forEach((m) => m.initUser(user));
|
||||
|
||||
// if (firebaseMessaging != null) {
|
||||
// firebaseMessaging.subscribeToTopic(user.docID);
|
||||
// }
|
||||
// }
|
||||
// if (firebaseMessaging != null) {
|
||||
// firebaseMessaging.subscribeToTopic(user.docID);
|
||||
// }
|
||||
}
|
||||
|
||||
void _initSetting(Setting setting) {
|
||||
models.forEach((m) => m.initSetting(setting));
|
||||
@@ -106,6 +107,7 @@ class MainModel extends ChangeNotifier {
|
||||
void _loadUser() async {
|
||||
try {
|
||||
this.user = await Services.instance.authService.getUser();
|
||||
_initUser(user);
|
||||
} finally {
|
||||
this.isLoaded = true;
|
||||
notifyListeners();
|
||||
@@ -143,13 +145,27 @@ class MainModel extends ChangeNotifier {
|
||||
|
||||
Future<void> signout() {
|
||||
this.user = null;
|
||||
// logout models
|
||||
models.forEach((m) => m.logout());
|
||||
notifyListeners();
|
||||
return Services.instance.authService.signout();
|
||||
}
|
||||
|
||||
Future<bool> hasInvite() async {
|
||||
return Services.instance.authService.hasInvite();
|
||||
}
|
||||
|
||||
Future<void> signup(String userName) async {
|
||||
await Services.instance.authService.signup(userName);
|
||||
this.user = await Services.instance.authService.getUser();
|
||||
this.user =
|
||||
await Services.instance.authService.getUser(refreshIdToken: true);
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
Future<void> updateProfile(String newUserName) async {
|
||||
await Services.instance.authService.updateProfile(newUserName);
|
||||
this.user =
|
||||
await Services.instance.authService.getUser(refreshIdToken: true);
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
|
||||
106
lib/fcs/common/pages/profile/profile_edit.dart
Normal file
106
lib/fcs/common/pages/profile/profile_edit.dart
Normal file
@@ -0,0 +1,106 @@
|
||||
import 'package:fcs/fcs/common/helpers/theme.dart';
|
||||
import 'package:fcs/fcs/common/localization/app_translations.dart';
|
||||
import 'package:fcs/fcs/common/pages/model/language_model.dart';
|
||||
import 'package:fcs/fcs/common/pages/model/main_model.dart';
|
||||
import 'package:fcs/fcs/common/pages/widgets/progress.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:fcs/fcs/common/pages/util.dart';
|
||||
|
||||
typedef void ProfileCallback();
|
||||
|
||||
class ProfileEdit extends StatefulWidget {
|
||||
@override
|
||||
_ProfileEditState createState() => _ProfileEditState();
|
||||
}
|
||||
|
||||
class _ProfileEditState extends State<ProfileEdit> {
|
||||
final TextEditingController nameController = new TextEditingController();
|
||||
bool _loading = false;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
MainModel mainModel = Provider.of<MainModel>(context, listen: false);
|
||||
nameController.text = mainModel.user.name;
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
var languageModel = Provider.of<LanguageModel>(context);
|
||||
|
||||
final name = Container(
|
||||
padding: EdgeInsets.only(top: 0, left: 20, right: 15, bottom: 30),
|
||||
child: TextFormField(
|
||||
controller: nameController,
|
||||
autofocus: true,
|
||||
cursorColor: primaryColor,
|
||||
style: textStyle,
|
||||
decoration: new InputDecoration(
|
||||
labelText: AppTranslations.of(context).text("profile.name"),
|
||||
labelStyle: languageModel.isEng ? labelStyle : labelStyleMM,
|
||||
icon: Icon(
|
||||
Icons.person,
|
||||
color: primaryColor,
|
||||
),
|
||||
enabledBorder: UnderlineInputBorder(
|
||||
borderSide: BorderSide(color: primaryColor, width: 1.0)),
|
||||
focusedBorder: UnderlineInputBorder(
|
||||
borderSide: BorderSide(color: primaryColor, width: 1.0)),
|
||||
),
|
||||
));
|
||||
|
||||
final saveBtn =
|
||||
fcsButton(context, getLocalString(context, "btn.save"), callack: _save);
|
||||
|
||||
return LocalProgress(
|
||||
inAsyncCall: _loading,
|
||||
child: Scaffold(
|
||||
appBar: AppBar(
|
||||
centerTitle: true,
|
||||
title: Text(
|
||||
AppTranslations.of(context).text("profile.edit_title"),
|
||||
style: TextStyle(color: primaryColor),
|
||||
),
|
||||
backgroundColor: Colors.white,
|
||||
shadowColor: Colors.transparent,
|
||||
leading: IconButton(
|
||||
icon: Icon(
|
||||
CupertinoIcons.back,
|
||||
size: 35,
|
||||
color: primaryColor,
|
||||
),
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
),
|
||||
),
|
||||
body: Column(
|
||||
children: <Widget>[
|
||||
Expanded(child: name),
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(18.0),
|
||||
child: saveBtn,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
_save() async {
|
||||
setState(() {
|
||||
_loading = true;
|
||||
});
|
||||
try {
|
||||
await Provider.of<MainModel>(context, listen: false)
|
||||
.updateProfile(nameController.text);
|
||||
Navigator.pop(context);
|
||||
} catch (e) {
|
||||
showMsgDialog(context, "Error", e.toString());
|
||||
} finally {
|
||||
setState(() {
|
||||
_loading = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,8 @@ import 'package:fcs/fcs/common/localization/app_translations.dart';
|
||||
import 'package:fcs/fcs/common/localization/transalation.dart';
|
||||
import 'package:fcs/fcs/common/pages/model/language_model.dart';
|
||||
import 'package:fcs/fcs/common/pages/model/main_model.dart';
|
||||
import 'package:fcs/fcs/common/pages/profile/profile_edit.dart';
|
||||
import 'package:fcs/fcs/common/pages/widgets/display_text.dart';
|
||||
import 'package:fcs/fcs/common/pages/widgets/progress.dart';
|
||||
import 'package:fcs/model/shipment_model.dart';
|
||||
import 'package:fcs/model/user_model.dart';
|
||||
@@ -12,10 +14,11 @@ import 'package:fcs/vo/shipping_address.dart';
|
||||
import 'package:fcs/widget/bottom_up_page_route.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
import '../../../pages/shipping_address_editor.dart';
|
||||
import '../helpers/theme.dart';
|
||||
import '../../../../pages/shipping_address_editor.dart';
|
||||
import '../../helpers/theme.dart';
|
||||
|
||||
typedef void ProfileCallback();
|
||||
|
||||
@@ -25,6 +28,7 @@ class Profile extends StatefulWidget {
|
||||
}
|
||||
|
||||
class _ProfileState extends State<Profile> {
|
||||
GlobalKey key = GlobalKey();
|
||||
bool _isLoading = false;
|
||||
String selectedLanguage;
|
||||
TextEditingController bizNameController = new TextEditingController();
|
||||
@@ -49,180 +53,112 @@ class _ProfileState extends State<Profile> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
var languageModel = Provider.of<LanguageModel>(context);
|
||||
MainModel mainModel = Provider.of<MainModel>(context);
|
||||
|
||||
final namebox = Container(
|
||||
padding: EdgeInsets.only(top: 10, left: 25.0, right: 25.0),
|
||||
child: Container(
|
||||
height: 45.0,
|
||||
child: Row(
|
||||
children: <Widget>[
|
||||
Padding(
|
||||
padding: EdgeInsets.only(left: 0.0),
|
||||
child: Text(
|
||||
AppTranslations.of(context).text("profile.name"),
|
||||
style: languageModel.isEng
|
||||
? TextStyle(
|
||||
fontSize: 16.0,
|
||||
fontWeight: FontWeight.bold,
|
||||
fontStyle: FontStyle.normal)
|
||||
: TextStyle(
|
||||
fontSize: 15.0,
|
||||
fontWeight: FontWeight.bold,
|
||||
fontStyle: FontStyle.normal,
|
||||
fontFamily: "MyanmarUnicode"),
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
width: 30,
|
||||
),
|
||||
Container(
|
||||
child: Center(
|
||||
child: Text(
|
||||
mainModel.user == null || mainModel.user.name == null
|
||||
? ""
|
||||
: mainModel.user.name,
|
||||
style:
|
||||
TextStyle(fontSize: 16.0, fontStyle: FontStyle.normal),
|
||||
),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
));
|
||||
|
||||
final phonenumberbox = Container(
|
||||
padding: EdgeInsets.only(left: 25.0, right: 25.0),
|
||||
height: 45.0,
|
||||
child: Row(
|
||||
children: <Widget>[
|
||||
Padding(
|
||||
padding: EdgeInsets.only(left: 0.0),
|
||||
child: Text(
|
||||
AppTranslations.of(context).text("profile.phone"),
|
||||
style: languageModel.isEng
|
||||
? TextStyle(
|
||||
fontSize: 16.0,
|
||||
fontWeight: FontWeight.bold,
|
||||
fontStyle: FontStyle.normal)
|
||||
: TextStyle(
|
||||
fontSize: 15.0,
|
||||
fontWeight: FontWeight.bold,
|
||||
fontStyle: FontStyle.normal,
|
||||
fontFamily: "MyanmarUnicode"),
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
width: 27,
|
||||
),
|
||||
Container(
|
||||
child: Center(
|
||||
child: Text(
|
||||
mainModel.user == null
|
||||
? ""
|
||||
: mainModel.user.phone == null ? '' : mainModel.user.phone,
|
||||
style: TextStyle(fontSize: 16.0, fontStyle: FontStyle.normal),
|
||||
),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
final namebox = DisplayText(
|
||||
text: mainModel.user.name,
|
||||
labelText: getLocalString(context, "profile.name"),
|
||||
iconData: Icons.person,
|
||||
);
|
||||
|
||||
final logoutbutton = Container(
|
||||
padding: EdgeInsets.only(left: 20.0, right: 24.0),
|
||||
child: Padding(
|
||||
padding: EdgeInsets.symmetric(vertical: 10.0),
|
||||
child: Card(
|
||||
elevation: 23,
|
||||
child: Container(
|
||||
height: 45.0,
|
||||
child: ButtonTheme(
|
||||
minWidth: 900.0,
|
||||
height: 100.0,
|
||||
child: FlatButton.icon(
|
||||
onPressed: () {
|
||||
showConfirmDialog(context, "profile.logout.confirm",
|
||||
() async {
|
||||
setState(() {
|
||||
_isLoading = true;
|
||||
});
|
||||
await context.read<MainModel>().signout();
|
||||
Navigator.of(context).pushNamedAndRemoveUntil(
|
||||
"/welcome", ModalRoute.withName('/welcome'));
|
||||
Future.delayed(Duration(seconds: 1), () {
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
_isLoading = false;
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
label: Text(
|
||||
AppTranslations.of(context).text("profile.logout"),
|
||||
style: languageModel.isEng
|
||||
? TextStyle(
|
||||
fontSize: 16.0,
|
||||
fontWeight: FontWeight.bold,
|
||||
fontStyle: FontStyle.normal)
|
||||
: TextStyle(
|
||||
fontSize: 16.0,
|
||||
fontWeight: FontWeight.bold,
|
||||
fontStyle: FontStyle.normal,
|
||||
fontFamily: "MyanmarUnicode")),
|
||||
icon: Icon(
|
||||
Icons.exit_to_app,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
)));
|
||||
final phonenumberbox = DisplayText(
|
||||
text: mainModel.user.phone,
|
||||
labelText: getLocalString(context, "profile.phone"),
|
||||
iconData: Icons.phone,
|
||||
);
|
||||
final fcsIDBox = Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: DisplayText(
|
||||
text: mainModel.user.fcsID,
|
||||
labelText: getLocalString(context, "customer.fcs.id"),
|
||||
iconData: Icons.account_circle,
|
||||
),
|
||||
),
|
||||
IconButton(
|
||||
icon: Icon(Icons.content_copy, color: Colors.grey),
|
||||
onPressed: () => _copy(
|
||||
getLocalString(context, "customer.fcs.id"), mainModel.user.fcsID),
|
||||
)
|
||||
],
|
||||
);
|
||||
final usaShippingAddressBox = Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: DisplayText(
|
||||
text: mainModel.setting.usaAddress,
|
||||
labelText: getLocalString(context, "profile.usa.shipping.address"),
|
||||
iconData: Icons.location_on,
|
||||
),
|
||||
),
|
||||
IconButton(
|
||||
icon: Icon(Icons.content_copy, color: Colors.grey),
|
||||
onPressed: () => _copy(
|
||||
getLocalString(context, "profile.usa.shipping.address"),
|
||||
mainModel.setting.usaAddress),
|
||||
)
|
||||
],
|
||||
);
|
||||
|
||||
final logoutbutton = fcsButton(
|
||||
context, getLocalString(context, "profile.logout"),
|
||||
callack: _logout, iconData: Icons.exit_to_app);
|
||||
|
||||
return LocalProgress(
|
||||
inAsyncCall: _isLoading,
|
||||
child: Scaffold(
|
||||
key: key,
|
||||
appBar: AppBar(
|
||||
centerTitle: true,
|
||||
leading: IconButton(
|
||||
icon: Icon(
|
||||
CupertinoIcons.back,
|
||||
size: 30,
|
||||
size: 35,
|
||||
color: primaryColor,
|
||||
),
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
),
|
||||
title: Text(
|
||||
AppTranslations.of(context).text("profile.title"),
|
||||
style: TextStyle(color: primaryColor),
|
||||
),
|
||||
backgroundColor: primaryColor,
|
||||
shadowColor: Colors.transparent,
|
||||
backgroundColor: Colors.white,
|
||||
actions: <Widget>[],
|
||||
),
|
||||
body: Column(
|
||||
children: <Widget>[
|
||||
Expanded(
|
||||
child: ListView(
|
||||
// padding: EdgeInsets.only(left: 25.0, right: 25.0),
|
||||
shrinkWrap: true,
|
||||
children: <Widget>[
|
||||
Row(
|
||||
children: <Widget>[
|
||||
namebox,
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(left: 18.0),
|
||||
child: Icon(Icons.edit, color: primaryColor),
|
||||
)
|
||||
],
|
||||
),
|
||||
mainModel.isCustomer()
|
||||
? Container()
|
||||
: getPrivilegeBox(context),
|
||||
phonenumberbox,
|
||||
// getShippingAddressList(context),
|
||||
],
|
||||
body: Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Column(
|
||||
children: <Widget>[
|
||||
Expanded(
|
||||
child: ListView(
|
||||
shrinkWrap: true,
|
||||
children: <Widget>[
|
||||
Row(
|
||||
children: <Widget>[
|
||||
Expanded(child: namebox),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(right: 0),
|
||||
child: IconButton(
|
||||
icon: Icon(Icons.edit, color: Colors.grey),
|
||||
onPressed: _editName),
|
||||
)
|
||||
],
|
||||
),
|
||||
// mainModel.isCustomer()
|
||||
// ? Container()
|
||||
// : getPrivilegeBox(context),
|
||||
phonenumberbox,
|
||||
fcsIDBox,
|
||||
usaShippingAddressBox,
|
||||
// getShippingAddressList(context),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
logoutbutton,
|
||||
SizedBox(height: 25)
|
||||
],
|
||||
logoutbutton,
|
||||
SizedBox(height: 25)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
@@ -347,4 +283,43 @@ class _ProfileState extends State<Profile> {
|
||||
);
|
||||
}).toList();
|
||||
}
|
||||
|
||||
_copy(String title, String data) {
|
||||
Clipboard.setData(ClipboardData(text: data));
|
||||
_showToast(title);
|
||||
}
|
||||
|
||||
void _showToast(String title) {
|
||||
final ScaffoldState scaffold = key.currentState;
|
||||
scaffold.showSnackBar(
|
||||
SnackBar(
|
||||
content: Text('copied "$title" data to clipboard'),
|
||||
backgroundColor: secondaryColor,
|
||||
duration: Duration(seconds: 1),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
_editName() {
|
||||
Navigator.of(context)
|
||||
.push<void>(CupertinoPageRoute(builder: (context) => ProfileEdit()));
|
||||
}
|
||||
|
||||
_logout() {
|
||||
showConfirmDialog(context, "profile.logout.confirm", () async {
|
||||
setState(() {
|
||||
_isLoading = true;
|
||||
});
|
||||
await context.read<MainModel>().signout();
|
||||
Navigator.of(context)
|
||||
.pushNamedAndRemoveUntil("/welcome", ModalRoute.withName('/welcome'));
|
||||
Future.delayed(Duration(seconds: 1), () {
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
_isLoading = false;
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,7 @@
|
||||
import 'package:fcs/fcs/common/pages/model/main_model.dart';
|
||||
import 'package:fcs/fcs/common/pages/signin/model/signin_model.dart';
|
||||
import 'package:fcs/fcs/common/pages/util.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
import '../../../../widget/local_text.dart';
|
||||
@@ -107,16 +105,17 @@ class _RequestInvitationPageState extends State<RequestInvitationPage> {
|
||||
_isLoading = true;
|
||||
});
|
||||
try {
|
||||
await context.read<SigninModel>().requestInvitation(nameCtl.text);
|
||||
// just signup to request for invitation
|
||||
await context.read<MainModel>().signup(nameCtl.text);
|
||||
await showMsgDialog(context, "Successful",
|
||||
getLocalString(context, "invite.request.successful"));
|
||||
Navigator.pushNamedAndRemoveUntil(context, "/home", (r) => false);
|
||||
} catch (e) {
|
||||
await showMsgDialog(context, "Error", e.toString());
|
||||
} finally {
|
||||
setState(() {
|
||||
_isLoading = false;
|
||||
});
|
||||
Navigator.pushNamedAndRemoveUntil(context, "/welcome", (r) => false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:fcs/fcs/common/pages/model/base_model.dart';
|
||||
import 'package:fcs/fcs/common/services/services.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
|
||||
class SigninModel extends BaseModel {
|
||||
final log = Logger('SigninModel');
|
||||
|
||||
Future<bool> checkInvatation() async {
|
||||
var invited = await request("/check_invitation", "GET",
|
||||
token: await Services.instance.authService.getToken());
|
||||
return invited["invited"];
|
||||
}
|
||||
|
||||
Future<void> requestInvitation(String name) async {
|
||||
await request("/request_invitation", "POST",
|
||||
payload: {"user_name": name},
|
||||
token: await Services.instance.authService.getToken());
|
||||
await Services.instance.authService.signout();
|
||||
}
|
||||
}
|
||||
31
lib/fcs/common/pages/signin/signin_logic.dart
Normal file
31
lib/fcs/common/pages/signin/signin_logic.dart
Normal file
@@ -0,0 +1,31 @@
|
||||
import 'package:fcs/fcs/common/domain/entities/setting.dart';
|
||||
import 'package:fcs/fcs/common/domain/entities/user.dart';
|
||||
import 'package:fcs/fcs/common/pages/model/main_model.dart';
|
||||
import 'package:fcs/fcs/common/pages/signin/invitation_request_page.dart';
|
||||
import 'package:fcs/fcs/common/pages/signin/signup_page.dart';
|
||||
import 'package:fcs/fcs/common/pages/widgets/bottom_up_page_route.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
navigateAfterAuthVerified(BuildContext context) async {
|
||||
User user = Provider.of<MainModel>(context, listen: false).user;
|
||||
Setting setting = Provider.of<MainModel>(context, listen: false).setting;
|
||||
|
||||
if (user == null || setting == null) return;
|
||||
|
||||
if (user.joined || user.requested) {
|
||||
Navigator.pushNamedAndRemoveUntil(context, "/home", (r) => false);
|
||||
} else {
|
||||
if (setting.inviteRequired) {
|
||||
bool invited =
|
||||
await Provider.of<MainModel>(context, listen: false).hasInvite();
|
||||
if (!invited) {
|
||||
await Navigator.of(context).pushAndRemoveUntil(
|
||||
BottomUpPageRoute(RequestInvitationPage()), (r) => false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
await Navigator.of(context)
|
||||
.pushAndRemoveUntil(BottomUpPageRoute(SignupPage()), (r) => false);
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,10 @@
|
||||
import 'package:country_code_picker/country_code_picker.dart';
|
||||
import 'package:fcs/fcs/common/domain/entities/auth_result.dart';
|
||||
import 'package:fcs/fcs/common/domain/entities/auth_status.dart';
|
||||
import 'package:fcs/fcs/common/domain/entities/setting.dart';
|
||||
import 'package:fcs/fcs/common/domain/entities/user.dart';
|
||||
import 'package:fcs/fcs/common/pages/model/main_model.dart';
|
||||
import 'package:fcs/fcs/common/pages/signin/signin_logic.dart';
|
||||
import 'package:fcs/fcs/common/pages/signin/signup_page.dart';
|
||||
import 'package:fcs/fcs/common/pages/widgets/local_text.dart';
|
||||
import 'package:fcs/widget/bottom_up_page_route.dart';
|
||||
@@ -179,12 +181,7 @@ class _SigninPageState extends State<SigninPage> {
|
||||
.push(BottomUpPageRoute(SmsCodePage(phoneNumber: phoneNumber)));
|
||||
Navigator.pop(context);
|
||||
} else if (auth.authStatus == AuthStatus.AUTH_VERIFIED) {
|
||||
User user = context.read<MainModel>().user;
|
||||
if (user != null && !user.hasSignup) {
|
||||
await Navigator.of(context).push(BottomUpPageRoute(SignupPage()));
|
||||
} else {
|
||||
Navigator.pushNamedAndRemoveUntil(context, "/home", (r) => false);
|
||||
}
|
||||
await navigateAfterAuthVerified(context);
|
||||
}
|
||||
if (auth.authStatus == AuthStatus.ERROR) {
|
||||
showMsgDialog(context, "Error", auth.authErrorMsg);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import 'package:fcs/fcs/common/pages/model/main_model.dart';
|
||||
import 'package:fcs/fcs/common/pages/util.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||
@@ -108,7 +109,18 @@ class _SignupPageState extends State<SignupPage> {
|
||||
}
|
||||
|
||||
_submit() async {
|
||||
await context.read<MainModel>().signup(nameCtl.text);
|
||||
Navigator.pushNamedAndRemoveUntil(context, "/home", (r) => false);
|
||||
setState(() {
|
||||
_isLoading = true;
|
||||
});
|
||||
try {
|
||||
await context.read<MainModel>().signup(nameCtl.text);
|
||||
Navigator.pushNamedAndRemoveUntil(context, "/home", (r) => false);
|
||||
} catch (e) {
|
||||
showMsgDialog(context, "Error", e.toString());
|
||||
} finally {
|
||||
setState(() {
|
||||
_isLoading = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,20 +2,16 @@ import 'dart:async';
|
||||
|
||||
import 'package:fcs/fcs/common/domain/entities/auth_result.dart';
|
||||
import 'package:fcs/fcs/common/domain/entities/auth_status.dart';
|
||||
import 'package:fcs/fcs/common/domain/entities/user.dart';
|
||||
import 'package:fcs/fcs/common/pages/model/main_model.dart';
|
||||
import 'package:fcs/fcs/common/pages/signin/model/signin_model.dart';
|
||||
import 'package:fcs/fcs/common/pages/signin/invitation_request_page.dart';
|
||||
import 'package:fcs/fcs/common/pages/signin/signin_logic.dart';
|
||||
import 'package:fcs/fcs/common/pages/util.dart';
|
||||
import 'package:fcs/fcs/common/pages/widgets/local_text.dart';
|
||||
import 'package:fcs/widget/bottom_up_page_route.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:pin_input_text_field/pin_input_text_field.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
import 'signup_page.dart';
|
||||
import '../../helpers/theme.dart';
|
||||
import '../../../../widget/progress.dart';
|
||||
import '../../helpers/theme.dart';
|
||||
|
||||
const resend_count_sec = 30;
|
||||
|
||||
@@ -202,18 +198,7 @@ class _SmsCodePageState extends State<SmsCodePage> {
|
||||
AuthResult auth = await context.read<MainModel>().signin(this.pin);
|
||||
|
||||
if (auth.authStatus == AuthStatus.AUTH_VERIFIED) {
|
||||
User user = context.read<MainModel>().user;
|
||||
if (user != null && !user.hasSignup) {
|
||||
bool invited = await context.read<SigninModel>().checkInvatation();
|
||||
if (invited) {
|
||||
await Navigator.of(context).push(BottomUpPageRoute(SignupPage()));
|
||||
} else {
|
||||
await Navigator.of(context)
|
||||
.push(BottomUpPageRoute(RequestInvitationPage()));
|
||||
}
|
||||
} else {
|
||||
Navigator.pushNamedAndRemoveUntil(context, "/home", (r) => false);
|
||||
}
|
||||
await navigateAfterAuthVerified(context);
|
||||
}
|
||||
} catch (e) {
|
||||
showMsgDialog(context, "Error", e.toString());
|
||||
|
||||
@@ -52,7 +52,7 @@ class _SplashScreenState extends State<SplashScreen> {
|
||||
if (mainModel.isLoaded) {
|
||||
if (mainModel.isFirstLaunch) {
|
||||
page = "/language_selection";
|
||||
} else if (mainModel.isLogin() && mainModel.user.hasSignup) {
|
||||
} else if (mainModel.isLogin()) {
|
||||
page = "/home";
|
||||
} else {
|
||||
page = "/welcome";
|
||||
|
||||
88
lib/fcs/common/pages/staff/model/staff_model.dart
Normal file
88
lib/fcs/common/pages/staff/model/staff_model.dart
Normal file
@@ -0,0 +1,88 @@
|
||||
import 'package:cloud_firestore/cloud_firestore.dart';
|
||||
import 'package:fcs/fcs/common/domain/constants.dart';
|
||||
import 'package:fcs/fcs/common/domain/entities/role.dart';
|
||||
import 'package:fcs/fcs/common/domain/entities/user.dart';
|
||||
import 'package:fcs/fcs/common/helpers/firebase_helper.dart';
|
||||
import 'package:fcs/fcs/common/pages/model/base_model.dart';
|
||||
import 'package:fcs/fcs/common/services/services.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
|
||||
class StaffModel extends BaseModel {
|
||||
final log = Logger('StaffModel');
|
||||
|
||||
List<User> employees = [];
|
||||
List<Privilege> privileges = [];
|
||||
|
||||
void initUser(user) async {
|
||||
super.initUser(user);
|
||||
_loadPrivileges();
|
||||
_loadEmployees();
|
||||
}
|
||||
|
||||
@override
|
||||
logout() async {
|
||||
employees = [];
|
||||
}
|
||||
|
||||
Future<void> _loadEmployees() async {
|
||||
if (user == null || !user.hasStaffs()) return;
|
||||
|
||||
try {
|
||||
Firestore.instance
|
||||
.collection("/$user_collection")
|
||||
.where("is_employee", isEqualTo: true)
|
||||
.where("is_sys_admin", isEqualTo: false)
|
||||
.snapshots()
|
||||
.listen((QuerySnapshot snapshot) {
|
||||
employees.clear();
|
||||
employees = snapshot.documents.map((documentSnapshot) {
|
||||
var user =
|
||||
User.fromMap(documentSnapshot.data, documentSnapshot.documentID);
|
||||
return user;
|
||||
}).toList();
|
||||
notifyListeners();
|
||||
}).onError((e) {
|
||||
log.warning("Error! $e");
|
||||
});
|
||||
} catch (e) {
|
||||
log.warning("Error!! $e");
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _loadPrivileges() async {
|
||||
if (user == null || !user.hasStaffs()) return;
|
||||
|
||||
try {
|
||||
Firestore.instance
|
||||
.collection("/$privilege_collection")
|
||||
.snapshots()
|
||||
.listen((QuerySnapshot snapshot) {
|
||||
privileges.clear();
|
||||
privileges = snapshot.documents.map((documentSnapshot) {
|
||||
var privilege = Privilege.fromMap(
|
||||
documentSnapshot.data, documentSnapshot.documentID);
|
||||
return privilege;
|
||||
}).toList();
|
||||
notifyListeners();
|
||||
}).onError((e) {
|
||||
log.warning("Error! $e");
|
||||
});
|
||||
} catch (e) {
|
||||
log.warning("Error!! $e");
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> updatePrivileges(String userID, List<String> privileges) async {
|
||||
try {
|
||||
await request("/employee/privileges", "PUT",
|
||||
payload: {"id": userID, "privileges": privileges},
|
||||
token: await getToken());
|
||||
} catch (e) {
|
||||
throw Exception(e);
|
||||
}
|
||||
}
|
||||
|
||||
Future<User> findUser(String phoneNumber) {
|
||||
return Services.instance.userService.findUser(phoneNumber);
|
||||
}
|
||||
}
|
||||
276
lib/fcs/common/pages/staff/staff_editor.dart
Normal file
276
lib/fcs/common/pages/staff/staff_editor.dart
Normal file
@@ -0,0 +1,276 @@
|
||||
import 'package:fcs/fcs/common/domain/entities/role.dart';
|
||||
import 'package:fcs/fcs/common/domain/entities/user.dart';
|
||||
import 'package:fcs/fcs/common/helpers/theme.dart';
|
||||
import 'package:fcs/fcs/common/localization/app_translations.dart';
|
||||
import 'package:fcs/fcs/common/pages/model/language_model.dart';
|
||||
import 'package:fcs/fcs/common/pages/staff/model/staff_model.dart';
|
||||
import 'package:fcs/fcs/common/pages/util.dart';
|
||||
import 'package:fcs/fcs/common/pages/widgets/display_text.dart';
|
||||
import 'package:fcs/fcs/common/pages/widgets/local_text.dart';
|
||||
import 'package:fcs/fcs/common/pages/widgets/progress.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
typedef void FindCallBack();
|
||||
|
||||
class StaffEditor extends StatefulWidget {
|
||||
final User staff;
|
||||
const StaffEditor({this.staff});
|
||||
@override
|
||||
_StaffEditorState createState() => _StaffEditorState();
|
||||
}
|
||||
|
||||
class _StaffEditorState extends State<StaffEditor> {
|
||||
TextEditingController _phoneInput = new TextEditingController();
|
||||
|
||||
bool _isLoading = false;
|
||||
User user;
|
||||
User selectedUser;
|
||||
List<Privilege> privileges = [];
|
||||
bool isNew = true;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
privileges = Provider.of<StaffModel>(context, listen: false).privileges;
|
||||
isNew = widget.staff == null;
|
||||
user = User();
|
||||
if (!isNew) {
|
||||
user =
|
||||
User(name: widget.staff.name, phoneNumber: widget.staff.phoneNumber);
|
||||
user.privileges = widget.staff.privileges;
|
||||
privileges.forEach((p) => user.privileges.contains(p.id)
|
||||
? p.isChecked = true
|
||||
: p.isChecked = false);
|
||||
} else {
|
||||
user.name = "";
|
||||
user.phoneNumber = "";
|
||||
privileges.forEach((p) => p.isChecked = false);
|
||||
}
|
||||
}
|
||||
|
||||
List<Widget> showprivilegeList(BuildContext context) {
|
||||
return privileges.map((p) {
|
||||
return new ListTile(
|
||||
title: InkWell(
|
||||
onTap: () {
|
||||
setState(() {
|
||||
p.isChecked = p.isChecked == null ? true : !p.isChecked;
|
||||
});
|
||||
},
|
||||
child: new Row(
|
||||
children: <Widget>[
|
||||
new Checkbox(
|
||||
value: p.isChecked == null ? false : p.isChecked,
|
||||
activeColor: primaryColor,
|
||||
onChanged: (bool value) {
|
||||
setState(() {
|
||||
p.isChecked = value;
|
||||
});
|
||||
}),
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
new Text(
|
||||
p.name,
|
||||
style: TextStyle(
|
||||
fontSize: 15.0,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
));
|
||||
}).toList();
|
||||
}
|
||||
|
||||
Widget phoneSearchbox(BuildContext context, FindCallBack findCallBack) {
|
||||
var languageModel = Provider.of<LanguageModel>(context);
|
||||
return Container(
|
||||
padding: EdgeInsets.only(bottom: 15, left: 8),
|
||||
child: Stack(
|
||||
alignment: const Alignment(1.2, 1.0),
|
||||
children: <Widget>[
|
||||
TextFormField(
|
||||
controller: _phoneInput,
|
||||
autofocus: false,
|
||||
cursorColor: primaryColor,
|
||||
keyboardType: TextInputType.phone,
|
||||
style: textStyle,
|
||||
decoration: new InputDecoration(
|
||||
labelText: AppTranslations.of(context).text('employee.phone'),
|
||||
labelStyle: languageModel.isEng ? labelStyle : labelStyleMM,
|
||||
icon: Icon(
|
||||
Icons.phone,
|
||||
color: primaryColor,
|
||||
),
|
||||
enabledBorder: UnderlineInputBorder(
|
||||
borderSide: BorderSide(color: primaryColor, width: 1.0)),
|
||||
focusedBorder: UnderlineInputBorder(
|
||||
borderSide: BorderSide(color: primaryColor, width: 1.0)),
|
||||
),
|
||||
),
|
||||
new FlatButton(
|
||||
onPressed: () {
|
||||
findCallBack();
|
||||
},
|
||||
child: new Icon(
|
||||
Icons.search,
|
||||
size: 25,
|
||||
))
|
||||
],
|
||||
));
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final namebox = DisplayText(
|
||||
text: user.name,
|
||||
labelText: getLocalString(context, "customer.name"),
|
||||
iconData: Icons.person,
|
||||
);
|
||||
var phoneNumberBox = Row(
|
||||
children: <Widget>[
|
||||
Expanded(
|
||||
child: DisplayText(
|
||||
text: user.phoneNumber,
|
||||
labelText: getLocalString(context, "customer.phone"),
|
||||
iconData: Icons.phone,
|
||||
)),
|
||||
IconButton(
|
||||
icon: Icon(Icons.open_in_new, color: primaryColor),
|
||||
onPressed: () => call(context, user.phoneNumber)),
|
||||
],
|
||||
);
|
||||
|
||||
final updateButton = fcsButton(
|
||||
context,
|
||||
getLocalString(context, 'staff.update'),
|
||||
callack: _save,
|
||||
);
|
||||
final addButton = fcsButton(
|
||||
context,
|
||||
getLocalString(context, 'staff.add'),
|
||||
callack: _add,
|
||||
);
|
||||
|
||||
return LocalProgress(
|
||||
inAsyncCall: _isLoading,
|
||||
child: Scaffold(
|
||||
appBar: AppBar(
|
||||
centerTitle: true,
|
||||
leading: new IconButton(
|
||||
icon: new Icon(Icons.close, color: primaryColor, size: 30),
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
),
|
||||
shadowColor: Colors.transparent,
|
||||
backgroundColor: Colors.white,
|
||||
title: LocalText(
|
||||
context,
|
||||
"staff.form.title",
|
||||
fontSize: 20,
|
||||
color: primaryColor,
|
||||
),
|
||||
),
|
||||
body: Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Column(
|
||||
children: <Widget>[
|
||||
isNew
|
||||
? phoneSearchbox(context, () => _findUser(context))
|
||||
: Container(),
|
||||
phoneNumberBox,
|
||||
namebox,
|
||||
Expanded(
|
||||
child: ListView(
|
||||
shrinkWrap: true,
|
||||
padding: EdgeInsets.only(left: 24.0, right: 24.0),
|
||||
children: showprivilegeList(context),
|
||||
),
|
||||
),
|
||||
Container(
|
||||
child: isNew ? addButton : updateButton,
|
||||
),
|
||||
SizedBox(
|
||||
height: 10,
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
));
|
||||
}
|
||||
|
||||
_add() async {
|
||||
if (isNew && selectedUser == null) {
|
||||
showMsgDialog(context, "Error", "Invalid user!");
|
||||
return;
|
||||
}
|
||||
setState(() {
|
||||
_isLoading = true;
|
||||
});
|
||||
StaffModel staffModel = Provider.of<StaffModel>(context, listen: false);
|
||||
try {
|
||||
await staffModel.updatePrivileges(this.selectedUser.id, privilegesIDs());
|
||||
Navigator.pop(context);
|
||||
} catch (e) {
|
||||
showMsgDialog(context, "Error", e.toString());
|
||||
} finally {
|
||||
setState(() {
|
||||
_isLoading = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
List<String> privilegesIDs() {
|
||||
return this.privileges.where((p) => p.isChecked).map((p) => p.id).toList();
|
||||
}
|
||||
|
||||
_save() async {
|
||||
setState(() {
|
||||
_isLoading = true;
|
||||
});
|
||||
if (widget.staff == null) return;
|
||||
StaffModel staffModel = Provider.of<StaffModel>(context, listen: false);
|
||||
try {
|
||||
await staffModel.updatePrivileges(widget.staff.id, privilegesIDs());
|
||||
Navigator.pop(context);
|
||||
} catch (e) {
|
||||
showMsgDialog(context, "Error", e.toString());
|
||||
} finally {
|
||||
setState(() {
|
||||
_isLoading = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
_findUser(BuildContext context) async {
|
||||
StaffModel staffModel = Provider.of<StaffModel>(context, listen: false);
|
||||
|
||||
setState(() {
|
||||
_isLoading = true;
|
||||
});
|
||||
try {
|
||||
User _user = await staffModel.findUser(_phoneInput.text);
|
||||
if (_user == null) {
|
||||
showMsgDialog(context, "Error", _phoneInput.text + " not found!");
|
||||
return;
|
||||
}
|
||||
this.selectedUser = _user;
|
||||
this.user = _user;
|
||||
setState(() {
|
||||
if (user.privileges != null) {
|
||||
privileges.forEach((p) => user.privileges.contains(p.id)
|
||||
? p.isChecked = true
|
||||
: p.isChecked = false);
|
||||
}
|
||||
});
|
||||
} catch (e) {
|
||||
showMsgDialog(context, "Error", e.toString());
|
||||
} finally {
|
||||
setState(() {
|
||||
_isLoading = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
124
lib/fcs/common/pages/staff/staff_list.dart
Normal file
124
lib/fcs/common/pages/staff/staff_list.dart
Normal file
@@ -0,0 +1,124 @@
|
||||
import 'package:fcs/fcs/common/domain/entities/user.dart';
|
||||
import 'package:fcs/fcs/common/localization/app_translations.dart';
|
||||
import 'package:fcs/fcs/common/pages/staff/model/staff_model.dart';
|
||||
import 'package:fcs/fcs/common/pages/widgets/bottom_up_page_route.dart';
|
||||
import 'package:fcs/fcs/common/pages/widgets/local_text.dart';
|
||||
import 'package:fcs/fcs/common/helpers/theme.dart';
|
||||
import 'package:fcs/fcs/common/pages/widgets/progress.dart';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_icons/flutter_icons.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
|
||||
import 'package:provider/provider.dart';
|
||||
import 'staff_editor.dart';
|
||||
|
||||
class StaffList extends StatefulWidget {
|
||||
@override
|
||||
_StaffListState createState() => _StaffListState();
|
||||
}
|
||||
|
||||
class _StaffListState extends State<StaffList> {
|
||||
var dateFormatter = new DateFormat('dd MMM yyyy - hh:mm:ss a');
|
||||
final double dotSize = 15.0;
|
||||
bool _isLoading = false;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
StaffModel staffModel = Provider.of<StaffModel>(context);
|
||||
|
||||
return LocalProgress(
|
||||
inAsyncCall: _isLoading,
|
||||
child: Scaffold(
|
||||
appBar: AppBar(
|
||||
centerTitle: true,
|
||||
leading: new IconButton(
|
||||
icon: new Icon(Icons.close),
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
),
|
||||
backgroundColor: primaryColor,
|
||||
title: LocalText(
|
||||
context,
|
||||
'staff.list.title',
|
||||
color: Colors.white,
|
||||
fontSize: 20,
|
||||
),
|
||||
),
|
||||
floatingActionButton: FloatingActionButton.extended(
|
||||
onPressed: () {
|
||||
Navigator.of(context).push(BottomUpPageRoute(StaffEditor()));
|
||||
},
|
||||
icon: Icon(Icons.add),
|
||||
label: Text(AppTranslations.of(context).text("staff.new")),
|
||||
backgroundColor: primaryColor,
|
||||
),
|
||||
body: new ListView.separated(
|
||||
separatorBuilder: (context, index) => Divider(
|
||||
color: Colors.black,
|
||||
),
|
||||
scrollDirection: Axis.vertical,
|
||||
padding: EdgeInsets.only(left: 5, right: 5, top: 5),
|
||||
shrinkWrap: true,
|
||||
itemCount: staffModel.employees.length,
|
||||
itemBuilder: (BuildContext context, int index) {
|
||||
User user = staffModel.employees[index];
|
||||
return _item(user);
|
||||
}),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _item(User user) {
|
||||
return Stack(
|
||||
children: <Widget>[
|
||||
InkWell(
|
||||
onTap: () {
|
||||
Navigator.of(context)
|
||||
.push(BottomUpPageRoute(StaffEditor(staff: user)));
|
||||
},
|
||||
child: Row(
|
||||
children: <Widget>[
|
||||
Expanded(
|
||||
child: new Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 10.0),
|
||||
child: new Row(
|
||||
children: <Widget>[
|
||||
new Padding(
|
||||
padding: new EdgeInsets.symmetric(
|
||||
horizontal: 32.0 - dotSize / 2),
|
||||
child: Icon(
|
||||
MaterialCommunityIcons.worker,
|
||||
color: primaryColor,
|
||||
size: 40,
|
||||
),
|
||||
),
|
||||
new Expanded(
|
||||
child: new Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
new Text(
|
||||
user.name,
|
||||
style: new TextStyle(fontSize: 15.0),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 8.0),
|
||||
child: new Text(
|
||||
user.phoneNumber,
|
||||
style: new TextStyle(
|
||||
fontSize: 15.0, color: Colors.grey),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -410,13 +410,18 @@ Widget phoneWidget(BuildContext context, String phone) {
|
||||
}
|
||||
|
||||
Widget fcsInput(String label, IconData iconData,
|
||||
{TextEditingController controller, String value}) {
|
||||
{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,
|
||||
@@ -553,7 +558,19 @@ Widget _dropDown() {
|
||||
);
|
||||
}
|
||||
|
||||
Widget fcsButton(BuildContext context, String text, {Function callack}) {
|
||||
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(
|
||||
@@ -567,12 +584,21 @@ Widget fcsButton(BuildContext context, String text, {Function callack}) {
|
||||
height: 100.0,
|
||||
child: FlatButton(
|
||||
onPressed: callack,
|
||||
child: Text(text,
|
||||
style: TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.bold,
|
||||
)),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
iconData == null
|
||||
? Container()
|
||||
: Icon(
|
||||
iconData,
|
||||
color: Colors.white,
|
||||
),
|
||||
SizedBox(
|
||||
width: 15,
|
||||
),
|
||||
Text(text, style: style),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
@@ -13,7 +13,7 @@ import 'package:logging/logging.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
import '../helpers/theme.dart';
|
||||
import 'profile_page.dart';
|
||||
import 'profile/profile_page.dart';
|
||||
import 'signin/signin_page.dart';
|
||||
|
||||
final msgLog = Logger('backgroundMessageHandler');
|
||||
|
||||
69
lib/fcs/common/pages/widgets/display_text.dart
Normal file
69
lib/fcs/common/pages/widgets/display_text.dart
Normal file
@@ -0,0 +1,69 @@
|
||||
import 'package:fcs/fcs/common/helpers/theme.dart';
|
||||
import 'package:fcs/fcs/common/pages/model/language_model.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class DisplayText extends StatelessWidget {
|
||||
final String text;
|
||||
final String labelText;
|
||||
final IconData iconData;
|
||||
final int maxLines;
|
||||
final bool withBorder;
|
||||
final Color borderColor;
|
||||
|
||||
const DisplayText({
|
||||
Key key,
|
||||
this.text,
|
||||
this.labelText,
|
||||
this.iconData,
|
||||
this.maxLines = 1,
|
||||
this.withBorder = false,
|
||||
this.borderColor,
|
||||
}) : super(key: key);
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
var languageModel = Provider.of<LanguageModel>(context);
|
||||
|
||||
var labelStyle = languageModel.isEng
|
||||
? TextStyle(
|
||||
color: Colors.black54,
|
||||
)
|
||||
: TextStyle(color: Colors.black54, fontFamily: "Myanmar3");
|
||||
var textStyle = languageModel.isEng
|
||||
? TextStyle(
|
||||
color: primaryColor,
|
||||
)
|
||||
: TextStyle(color: primaryColor, fontFamily: "Myanmar3");
|
||||
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(top: 8.0, bottom: 8),
|
||||
child: Row(
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Icon(
|
||||
iconData,
|
||||
color: primaryColor,
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
labelText,
|
||||
style: labelStyle,
|
||||
),
|
||||
Text(
|
||||
text,
|
||||
style: textStyle,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
import 'package:fcs/fcs/common/data/providers/auth_fb.dart';
|
||||
import 'package:fcs/fcs/common/data/providers/user_fb_data_provider.dart';
|
||||
import 'package:fcs/fcs/common/data/providers/user_data_provider.dart';
|
||||
import 'package:fcs/fcs/common/data/providers/user_local_data_provider.dart';
|
||||
import 'package:fcs/fcs/common/domain/entities/auth_result.dart';
|
||||
import 'package:fcs/fcs/common/domain/entities/connectivity.dart';
|
||||
@@ -13,12 +13,10 @@ class AuthServiceImp implements AuthService {
|
||||
AuthServiceImp({
|
||||
@required this.authFb,
|
||||
@required this.connectivity,
|
||||
@required this.userFBDataProvider,
|
||||
@required this.userLocalDataProvider,
|
||||
});
|
||||
|
||||
final Connectivity connectivity;
|
||||
final UserFBDataProvider userFBDataProvider;
|
||||
final UserLocalDataProvider userLocalDataProvider;
|
||||
final AuthFb authFb;
|
||||
|
||||
@@ -61,4 +59,14 @@ class AuthServiceImp implements AuthService {
|
||||
Future<String> getToken() {
|
||||
return authFb.getToken();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<bool> hasInvite() {
|
||||
return authFb.hasInvite();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> updateProfile(String newUserName) {
|
||||
return authFb.updateProfile(newUserName);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,8 @@ abstract class AuthService {
|
||||
Future<void> signout();
|
||||
Future<User> getUser({bool refreshIdToken = false});
|
||||
Future<User> signup(String userName);
|
||||
Future<void> updateProfile(String newUserName);
|
||||
Future<bool> hasInvite();
|
||||
Stream<Setting> getSetting();
|
||||
Stream<User> onAuthStatus();
|
||||
Future<String> getToken();
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
import 'package:fcs/fcs/common/data/providers/auth_fb.dart';
|
||||
import 'package:fcs/fcs/common/data/providers/user_data_provider.dart';
|
||||
import 'package:fcs/fcs/common/services/auth_imp.dart';
|
||||
import 'package:fcs/fcs/common/services/messaging_imp.dart';
|
||||
import 'package:fcs/fcs/common/services/messaging_service.dart';
|
||||
import 'package:fcs/fcs/common/services/user_imp.dart';
|
||||
import 'package:fcs/fcs/common/services/user_service.dart';
|
||||
|
||||
import 'auth_service.dart';
|
||||
|
||||
@@ -9,16 +12,19 @@ class Services {
|
||||
static final Services instance = Services._();
|
||||
|
||||
AuthService _authService;
|
||||
UserService _userService;
|
||||
MessagingService _messagingService;
|
||||
Services._() {
|
||||
_authService = AuthServiceImp(
|
||||
authFb: AuthFb.instance,
|
||||
connectivity: null,
|
||||
userFBDataProvider: null,
|
||||
userLocalDataProvider: null);
|
||||
_userService = UserServiceImp(
|
||||
connectivity: null, userDataProvider: UserDataProvider());
|
||||
_messagingService = MessagingServiceImp();
|
||||
}
|
||||
|
||||
AuthService get authService => _authService;
|
||||
UserService get userService => _userService;
|
||||
MessagingService get messagingService => _messagingService;
|
||||
}
|
||||
|
||||
@@ -1,33 +1,36 @@
|
||||
import 'package:fcs/fcs/common/data/providers/user_data_provider.dart';
|
||||
import 'package:fcs/fcs/common/domain/entities/connectivity.dart';
|
||||
import 'package:fcs/fcs/common/domain/entities/user.dart';
|
||||
import 'package:fcs/fcs/common/domain/exceiptions/server_exceptions.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'user_interface.dart';
|
||||
import 'user_service.dart';
|
||||
|
||||
class UserImp implements UserInterface {
|
||||
UserImp({
|
||||
class UserServiceImp implements UserService {
|
||||
UserServiceImp({
|
||||
@required this.connectivity,
|
||||
@required this.userDataProvider,
|
||||
});
|
||||
|
||||
final Connectivity connectivity;
|
||||
final UserDataProvider userDataProvider;
|
||||
|
||||
@override
|
||||
Future<User> getUser(String id) async {
|
||||
if (connectivity.isConnected) {
|
||||
try {
|
||||
final User user = User();
|
||||
// await userFBDataProvider.getUser(id);
|
||||
// cache product
|
||||
// productLocalDataProvider.cacheProduct(product);
|
||||
return user;
|
||||
} catch (e) {
|
||||
print(e);
|
||||
return ServerException()();
|
||||
}
|
||||
} else {
|
||||
return Future.value(User());
|
||||
// return userLocalDataProvider.getUser(id);
|
||||
}
|
||||
Future<void> inviteUser(String userName, String phoneNumber) {
|
||||
return userDataProvider.inviteUser(userName, phoneNumber);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> deleteInvite(String phoneNumber) {
|
||||
return userDataProvider.deleteInvite(phoneNumber);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> acceptRequest(String userID) {
|
||||
return userDataProvider.acceptRequest(userID);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<User> findUser(String phoneNumber) {
|
||||
return userDataProvider.findUser(phoneNumber);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
import 'package:fcs/fcs/common/domain/entities/user.dart';
|
||||
|
||||
abstract class UserInterface {
|
||||
Future<User> getUser(String id);
|
||||
}
|
||||
8
lib/fcs/common/services/user_service.dart
Normal file
8
lib/fcs/common/services/user_service.dart
Normal file
@@ -0,0 +1,8 @@
|
||||
import 'package:fcs/fcs/common/domain/entities/user.dart';
|
||||
|
||||
abstract class UserService {
|
||||
Future<void> inviteUser(String userName, String phoneNumber);
|
||||
Future<void> deleteInvite(String phoneNumber);
|
||||
Future<void> acceptRequest(String userID);
|
||||
Future<User> findUser(String phoneNumber);
|
||||
}
|
||||
37
pubspec.lock
37
pubspec.lock
@@ -245,7 +245,21 @@ packages:
|
||||
name: firebase_auth
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.14.0+9"
|
||||
version: "0.16.1"
|
||||
firebase_auth_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: firebase_auth_platform_interface
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.1.8"
|
||||
firebase_auth_web:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: firebase_auth_web
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.1.3+1"
|
||||
firebase_core:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@@ -328,6 +342,20 @@ packages:
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.7.5"
|
||||
flutter_local_notifications:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: flutter_local_notifications
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.4.4+4"
|
||||
flutter_local_notifications_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: flutter_local_notifications_platform_interface
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.1"
|
||||
flutter_localizations:
|
||||
dependency: "direct main"
|
||||
description: flutter
|
||||
@@ -709,6 +737,13 @@ packages:
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.0"
|
||||
share:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: share
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.6.5"
|
||||
shared_preferences:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
||||
@@ -75,6 +75,7 @@ dependencies:
|
||||
barcode_scan: ^3.0.1
|
||||
flutter_pdfview: ^1.0.3
|
||||
flutter_local_notifications: ^1.4.4+4
|
||||
share: ^0.6.5
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user