add update phone number and recovery email
This commit is contained in:
@@ -19,6 +19,7 @@
|
|||||||
"btn.clear":"Clear Filter",
|
"btn.clear":"Clear Filter",
|
||||||
"btn.filter":"Filter",
|
"btn.filter":"Filter",
|
||||||
"btn.exit_confirm":"Are you sure you want to exit?",
|
"btn.exit_confirm":"Are you sure you want to exit?",
|
||||||
|
"btn.confirm":"Confirm",
|
||||||
"Buttons End ================================================================":"",
|
"Buttons End ================================================================":"",
|
||||||
|
|
||||||
"Offline Start ================================================================":"",
|
"Offline Start ================================================================":"",
|
||||||
@@ -76,6 +77,8 @@
|
|||||||
"Login Start ================================================================":"",
|
"Login Start ================================================================":"",
|
||||||
"login.title":"Sign in to FCS",
|
"login.title":"Sign in to FCS",
|
||||||
"login.phone":"Enter phone number",
|
"login.phone":"Enter phone number",
|
||||||
|
"login.phone_number":"Phone Number",
|
||||||
|
"login.phone_empty":"Enter phone number",
|
||||||
"Login End ================================================================":"",
|
"Login End ================================================================":"",
|
||||||
|
|
||||||
"SMS Start ================================================================":"",
|
"SMS Start ================================================================":"",
|
||||||
@@ -83,6 +86,7 @@
|
|||||||
"sms.six.digit":"Enter 6 digit sms code sent to",
|
"sms.six.digit":"Enter 6 digit sms code sent to",
|
||||||
"sms.resend":"Resend",
|
"sms.resend":"Resend",
|
||||||
"sms.resend.seconds":"Resend again in {0} seconds",
|
"sms.resend.seconds":"Resend again in {0} seconds",
|
||||||
|
"sms.code":"SMS Code",
|
||||||
"SMS End ================================================================":"",
|
"SMS End ================================================================":"",
|
||||||
|
|
||||||
"FAQ Start ================================================================":"",
|
"FAQ Start ================================================================":"",
|
||||||
@@ -132,6 +136,7 @@
|
|||||||
"customer.list.title":"Customers",
|
"customer.list.title":"Customers",
|
||||||
"customer.name":"Name",
|
"customer.name":"Name",
|
||||||
"customer.phone":"Phone number",
|
"customer.phone":"Phone number",
|
||||||
|
"customer.phone_empty":"Please insert phone number",
|
||||||
"customer.status":"Status",
|
"customer.status":"Status",
|
||||||
"customer.fcs.id":"FCS ID",
|
"customer.fcs.id":"FCS ID",
|
||||||
"customer.invitation.request.confirm":"Accept customer",
|
"customer.invitation.request.confirm":"Accept customer",
|
||||||
@@ -183,6 +188,21 @@
|
|||||||
"profile.email":"Email",
|
"profile.email":"Email",
|
||||||
"profile.privileges":"Privileges",
|
"profile.privileges":"Privileges",
|
||||||
"profile.default.delivery.address":"Default delivery address",
|
"profile.default.delivery.address":"Default delivery address",
|
||||||
|
"profile.recovery.email":"Recovery Email",
|
||||||
|
"profile.change_phone.title":"Change Phone Number",
|
||||||
|
"profile.current_phone":"Current Phone Number",
|
||||||
|
"profile.new_phone":"New Phone Number",
|
||||||
|
"profile.new_phone_empty":"Enter new phone number",
|
||||||
|
"profile.send_sms":"Send SMS Code",
|
||||||
|
"profile.confirm_new_phone.title":"Confirm New Phone Number",
|
||||||
|
"profile.change_phone.btn":"Change",
|
||||||
|
"profile.recovery_email.title":"Recovery Email",
|
||||||
|
"profile.email.empty":"Enter recovery email",
|
||||||
|
"profile.email.mismatch_message":"Email format is incorrect",
|
||||||
|
"profile.email_instruction":"Your recovery email is used to help you get back into your account when you can’t sign in.",
|
||||||
|
"profile.comfirm_email.title":"Confirm Your Email",
|
||||||
|
"profile.confirm_email.send_to":"Sent email to",
|
||||||
|
"profile.confirm_email.insruction":"Please open the email to confirm recovery email",
|
||||||
"Profile End ================================================================":"",
|
"Profile End ================================================================":"",
|
||||||
|
|
||||||
"Package Start ================================================================":"",
|
"Package Start ================================================================":"",
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
"btn.clear":"Clear Filter",
|
"btn.clear":"Clear Filter",
|
||||||
"btn.filter":"Filter",
|
"btn.filter":"Filter",
|
||||||
"btn.exit_confirm":"Are you sure you want to exit?",
|
"btn.exit_confirm":"Are you sure you want to exit?",
|
||||||
|
"btn.confirm":"အတည်ပြုမည်",
|
||||||
"Buttons End ================================================================":"",
|
"Buttons End ================================================================":"",
|
||||||
|
|
||||||
"Offline Start ================================================================":"",
|
"Offline Start ================================================================":"",
|
||||||
@@ -75,6 +76,8 @@
|
|||||||
"Login Start ================================================================":"",
|
"Login Start ================================================================":"",
|
||||||
"login.title":"FCS သို့အကောင့်ဒ်၀င်ပါ",
|
"login.title":"FCS သို့အကောင့်ဒ်၀င်ပါ",
|
||||||
"login.phone":"ဖုန်းနံပါတ်ထည့်ပါ",
|
"login.phone":"ဖုန်းနံပါတ်ထည့်ပါ",
|
||||||
|
"login.phone_number":"ဖုန်းနံပါတ်",
|
||||||
|
"login.phone_empty":"ဖုန်းနံပါတ်ထည့်ပါ",
|
||||||
"Login End ================================================================":"",
|
"Login End ================================================================":"",
|
||||||
|
|
||||||
"SMS Start ================================================================":"",
|
"SMS Start ================================================================":"",
|
||||||
@@ -82,6 +85,7 @@
|
|||||||
"sms.six.digit":"SMS ဂဏန်း ခြောက်လုံး ကိုရိုက်ထဲ့ပါ",
|
"sms.six.digit":"SMS ဂဏန်း ခြောက်လုံး ကိုရိုက်ထဲ့ပါ",
|
||||||
"sms.resend":"ပြန်ပို့ရန်",
|
"sms.resend":"ပြန်ပို့ရန်",
|
||||||
"sms.resend.seconds":"SMS ပြန်ပို့ရန် {0} စက္ကန့် စောင့်ပါ",
|
"sms.resend.seconds":"SMS ပြန်ပို့ရန် {0} စက္ကန့် စောင့်ပါ",
|
||||||
|
"sms.code":"SMS Code",
|
||||||
"SMS End ================================================================":"",
|
"SMS End ================================================================":"",
|
||||||
|
|
||||||
"FAQ Start ================================================================":"",
|
"FAQ Start ================================================================":"",
|
||||||
@@ -132,6 +136,7 @@
|
|||||||
"customer.list.title":"ဝယ်ယူသူများ",
|
"customer.list.title":"ဝယ်ယူသူများ",
|
||||||
"customer.name":"နာမည်",
|
"customer.name":"နာမည်",
|
||||||
"customer.phone":"ဖုန်းနံပါတ်",
|
"customer.phone":"ဖုန်းနံပါတ်",
|
||||||
|
"customer.phone_empty":"Please insert phone number",
|
||||||
"customer.status":"အခြေအနေ",
|
"customer.status":"အခြေအနေ",
|
||||||
"customer.fcs.id":"FCS ID",
|
"customer.fcs.id":"FCS ID",
|
||||||
"customer.invitation.request.confirm":"လက်ခံ လိုက်ပါ",
|
"customer.invitation.request.confirm":"လက်ခံ လိုက်ပါ",
|
||||||
@@ -184,6 +189,21 @@
|
|||||||
"profile.email":"အီးမေးလ်",
|
"profile.email":"အီးမေးလ်",
|
||||||
"profile.privileges":"လုပ်ပိုင်ခွင့်များ",
|
"profile.privileges":"လုပ်ပိုင်ခွင့်များ",
|
||||||
"profile.default.delivery.address":"အမြဲတမ်း ပို့ဆောင်ရမည့်လိပ်စာ",
|
"profile.default.delivery.address":"အမြဲတမ်း ပို့ဆောင်ရမည့်လိပ်စာ",
|
||||||
|
"profile.recovery.email":"အီးမေးလ်",
|
||||||
|
"profile.change_phone.title":"ဖုန်းနံပါတ်ပြောင်းခြင်း",
|
||||||
|
"profile.current_phone":"လက်ရှိဖုန်းနံပါတ်",
|
||||||
|
"profile.new_phone":"ဖုန်းနံပါတ်အသစ်",
|
||||||
|
"profile.new_phone_empty":"ဖုန်းနံပါတ်အသစ်ထည့်ပါ",
|
||||||
|
"profile.send_sms":"SMS ကုဒ်ပို့မည်",
|
||||||
|
"profile.confirm_new_phone.title":"ဖုန်းနံပါတ်အသစ်ကို အတည်ပြုခြင်း",
|
||||||
|
"profile.change_phone.btn":"ပြောင်းမည်",
|
||||||
|
"profile.recovery_email.title":"အီးမေးလ်ထည့်ခြင်း",
|
||||||
|
"profile.email.empty":"အီးမေးလ်ထည့်ပါ",
|
||||||
|
"profile.email.mismatch_message":"အီးမေးလ်မမှန်ပါ",
|
||||||
|
"profile.email_instruction":"အကောင့်ဝင်လို့မရသောအခါတွင် သင့်အကောင့်ထဲသို့ ပြန်လည်ရောက်ရှိစေရန်အတွက် သင်၏အီးမေးလ်ကို အသုံးပြုပါသည်။",
|
||||||
|
"profile.comfirm_email.title":"သင့်အီးမေးလ်ကိုအတည်ပြုခြင်း",
|
||||||
|
"profile.confirm_email.send_to":"သင့်အီးမေးလ်သို့ ပေးပို့ခဲ့သည်",
|
||||||
|
"profile.confirm_email.insruction":"အီးမေးလ်ကို အတည်ပြုရန် သင့်အီးမေးလ်ကိုဖွင့်ပါ",
|
||||||
"Profile End ================================================================":"",
|
"Profile End ================================================================":"",
|
||||||
|
|
||||||
"Package Start ================================================================":"",
|
"Package Start ================================================================":"",
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:flutter_localizations/flutter_localizations.dart';
|
import 'package:flutter_localizations/flutter_localizations.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
|
import 'helpers/theme.dart';
|
||||||
import 'pages/carton/model/carton_selection_model.dart';
|
import 'pages/carton/model/carton_selection_model.dart';
|
||||||
import 'pages/carton/model/consignee_selection_model.dart';
|
import 'pages/carton/model/consignee_selection_model.dart';
|
||||||
import 'pages/carton/model/package_selection_model.dart';
|
import 'pages/carton/model/package_selection_model.dart';
|
||||||
@@ -165,6 +166,8 @@ class _AppState extends State<App> {
|
|||||||
debugShowCheckedModeBanner: false,
|
debugShowCheckedModeBanner: false,
|
||||||
theme: ThemeData(
|
theme: ThemeData(
|
||||||
// useMaterial3: false,
|
// useMaterial3: false,
|
||||||
|
textSelectionTheme:
|
||||||
|
const TextSelectionThemeData(cursorColor: primaryColor),
|
||||||
dividerTheme: DividerThemeData(color: Colors.grey.shade200),
|
dividerTheme: DividerThemeData(color: Colors.grey.shade200),
|
||||||
colorScheme: ColorScheme.light(primary: Colors.white),
|
colorScheme: ColorScheme.light(primary: Colors.white),
|
||||||
dialogTheme: DialogTheme(
|
dialogTheme: DialogTheme(
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
const uploadPhotoLimit = 10;
|
const uploadPhotoLimit = 10;
|
||||||
const shipmentCountForCartonFilter = 10;
|
const shipmentCountForCartonFilter = 10;
|
||||||
|
const resendCountSec = 30;
|
||||||
|
|
||||||
const config_collection = "configs";
|
const config_collection = "configs";
|
||||||
const user_collection = "users";
|
const user_collection = "users";
|
||||||
|
|||||||
@@ -29,7 +29,8 @@ class AuthFb {
|
|||||||
StreamSubscription<DocumentSnapshot>? userListener;
|
StreamSubscription<DocumentSnapshot>? userListener;
|
||||||
StreamSubscription<DocumentSnapshot>? userAuthListener;
|
StreamSubscription<DocumentSnapshot>? userAuthListener;
|
||||||
|
|
||||||
Future<fcs.AuthResult> sendSmsCodeToPhoneNumber(String phoneNumber) {
|
Future<fcs.AuthResult> sendSmsCodeToPhoneNumber(String phoneNumber,
|
||||||
|
{String? forceResendingToken}) {
|
||||||
Completer<fcs.AuthResult> completer = Completer();
|
Completer<fcs.AuthResult> completer = Completer();
|
||||||
bool codeSentCompleted = false;
|
bool codeSentCompleted = false;
|
||||||
|
|
||||||
@@ -66,7 +67,9 @@ class AuthFb {
|
|||||||
print("codeSent " + phoneNumber);
|
print("codeSent " + phoneNumber);
|
||||||
codeSentCompleted = true;
|
codeSentCompleted = true;
|
||||||
if (!completer.isCompleted)
|
if (!completer.isCompleted)
|
||||||
completer.complete(fcs.AuthResult(authStatus: AuthStatus.SMS_SENT));
|
completer.complete(fcs.AuthResult(
|
||||||
|
authStatus: AuthStatus.SMS_SENT,
|
||||||
|
forceResendingToken: forceResendingToken?.toString()));
|
||||||
};
|
};
|
||||||
|
|
||||||
final fb.PhoneCodeAutoRetrievalTimeout codeAutoRetrievalTimeout =
|
final fb.PhoneCodeAutoRetrievalTimeout codeAutoRetrievalTimeout =
|
||||||
@@ -83,6 +86,9 @@ class AuthFb {
|
|||||||
};
|
};
|
||||||
|
|
||||||
_fb.verifyPhoneNumber(
|
_fb.verifyPhoneNumber(
|
||||||
|
forceResendingToken: forceResendingToken != null
|
||||||
|
? int.tryParse(forceResendingToken)
|
||||||
|
: null,
|
||||||
phoneNumber: phoneNumber,
|
phoneNumber: phoneNumber,
|
||||||
timeout: const Duration(seconds: 0),
|
timeout: const Duration(seconds: 0),
|
||||||
verificationCompleted: verificationCompleted,
|
verificationCompleted: verificationCompleted,
|
||||||
|
|||||||
@@ -16,8 +16,10 @@ class AuthServiceImp implements AuthService {
|
|||||||
final AuthFb authFb;
|
final AuthFb authFb;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<AuthResult> sendSmsCodeToPhoneNumber(String phoneNumber) {
|
Future<AuthResult> sendSmsCodeToPhoneNumber(String phoneNumber,
|
||||||
return authFb.sendSmsCodeToPhoneNumber(phoneNumber);
|
{String? forceResendingToken}) {
|
||||||
|
return authFb.sendSmsCodeToPhoneNumber(phoneNumber,
|
||||||
|
forceResendingToken: forceResendingToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|||||||
@@ -3,7 +3,8 @@ import 'package:fcs/domain/entities/setting.dart';
|
|||||||
import 'package:fcs/domain/entities/user.dart';
|
import 'package:fcs/domain/entities/user.dart';
|
||||||
|
|
||||||
abstract class AuthService {
|
abstract class AuthService {
|
||||||
Future<AuthResult> sendSmsCodeToPhoneNumber(String phoneNumber);
|
Future<AuthResult> sendSmsCodeToPhoneNumber(String phoneNumber,
|
||||||
|
{String? forceResendingToken});
|
||||||
Future<AuthResult> signInWithSmsCode(String smsCode);
|
Future<AuthResult> signInWithSmsCode(String smsCode);
|
||||||
Future<void> signoutStart();
|
Future<void> signoutStart();
|
||||||
Future<void> signoutEnd();
|
Future<void> signoutEnd();
|
||||||
|
|||||||
@@ -4,6 +4,11 @@ class AuthResult {
|
|||||||
AuthStatus? authStatus;
|
AuthStatus? authStatus;
|
||||||
String? authErrorCode;
|
String? authErrorCode;
|
||||||
String? authErrorMsg;
|
String? authErrorMsg;
|
||||||
|
String? forceResendingToken;
|
||||||
|
|
||||||
AuthResult({this.authStatus, this.authErrorCode, this.authErrorMsg});
|
AuthResult(
|
||||||
|
{this.authStatus,
|
||||||
|
this.authErrorCode,
|
||||||
|
this.authErrorMsg,
|
||||||
|
this.forceResendingToken});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ class User {
|
|||||||
bool enablePinLogin;
|
bool enablePinLogin;
|
||||||
String? pinDigit;
|
String? pinDigit;
|
||||||
List<String> privileges = [];
|
List<String> privileges = [];
|
||||||
|
String? recoveryEmail;
|
||||||
|
|
||||||
String get initial =>
|
String get initial =>
|
||||||
name != null && name != "" ? name!.substring(0, 1) : "?";
|
name != null && name != "" ? name!.substring(0, 1) : "?";
|
||||||
@@ -51,7 +52,7 @@ class User {
|
|||||||
|
|
||||||
// for pin login
|
// for pin login
|
||||||
String? pinToken;
|
String? pinToken;
|
||||||
bool get isPinLogin => pinToken!=null;
|
bool get isPinLogin => pinToken != null;
|
||||||
|
|
||||||
String get phone => phoneNumber != null && phoneNumber!.startsWith("959")
|
String get phone => phoneNumber != null && phoneNumber!.startsWith("959")
|
||||||
? "0${phoneNumber!.substring(2)}"
|
? "0${phoneNumber!.substring(2)}"
|
||||||
@@ -62,21 +63,21 @@ class User {
|
|||||||
bool get disabled => status != null && status == user_disabled_status;
|
bool get disabled => status != null && status == user_disabled_status;
|
||||||
|
|
||||||
String get share => "Your phone number:$phoneNumber";
|
String get share => "Your phone number:$phoneNumber";
|
||||||
User({
|
User(
|
||||||
this.id,
|
{this.id,
|
||||||
this.name,
|
this.name,
|
||||||
this.phoneNumber,
|
this.phoneNumber,
|
||||||
this.fcsID,
|
this.fcsID,
|
||||||
this.status,
|
this.status,
|
||||||
this.privileges = const [],
|
this.privileges = const [],
|
||||||
this.lastMessage,
|
this.lastMessage,
|
||||||
this.lastMessageTime,
|
this.lastMessageTime,
|
||||||
this.userUnseenCount = 0,
|
this.userUnseenCount = 0,
|
||||||
this.fcsUnseenCount = 0,
|
this.fcsUnseenCount = 0,
|
||||||
this.preferCurrency,
|
this.preferCurrency,
|
||||||
this.enablePinLogin = false,
|
this.enablePinLogin = false,
|
||||||
this.pinDigit,
|
this.pinDigit,
|
||||||
});
|
this.recoveryEmail});
|
||||||
|
|
||||||
factory User.fromJson(Map<String, dynamic> json) {
|
factory User.fromJson(Map<String, dynamic> json) {
|
||||||
return User(
|
return User(
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ const buttonBkColor = const Color(0xFF268944);
|
|||||||
const labelColor = const Color(0xFF757575);
|
const labelColor = const Color(0xFF757575);
|
||||||
var dividerColor = Colors.grey.shade400;
|
var dividerColor = Colors.grey.shade400;
|
||||||
const dangerColor = const Color(0xffff0606);
|
const dangerColor = const Color(0xffff0606);
|
||||||
|
const hintTextColor = Color.fromARGB(255, 187, 187, 187);
|
||||||
|
|
||||||
const TextStyle labelStyle =
|
const TextStyle labelStyle =
|
||||||
TextStyle(fontSize: 20, color: labelColor, fontWeight: FontWeight.w500);
|
TextStyle(fontSize: 20, color: labelColor, fontWeight: FontWeight.w500);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import 'package:country_code_picker/country_code_picker.dart';
|
import 'package:country_picker/country_picker.dart';
|
||||||
import 'package:fcs/helpers/theme.dart';
|
import 'package:fcs/helpers/theme.dart';
|
||||||
import 'package:fcs/pages/customer/model/customer_model.dart';
|
import 'package:fcs/pages/customer/model/customer_model.dart';
|
||||||
import 'package:fcs/pages/main/util.dart';
|
import 'package:fcs/pages/main/util.dart';
|
||||||
@@ -8,6 +8,8 @@ import 'package:fcs/pages/widgets/progress.dart';
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
|
import '../widgets/input_phone.dart';
|
||||||
|
|
||||||
class InvitationCreate extends StatefulWidget {
|
class InvitationCreate extends StatefulWidget {
|
||||||
@override
|
@override
|
||||||
_InvitationCreateState createState() => _InvitationCreateState();
|
_InvitationCreateState createState() => _InvitationCreateState();
|
||||||
@@ -18,13 +20,23 @@ class _InvitationCreateState extends State<InvitationCreate> {
|
|||||||
TextEditingController _phoneController = new TextEditingController();
|
TextEditingController _phoneController = new TextEditingController();
|
||||||
|
|
||||||
bool _isLoading = false;
|
bool _isLoading = false;
|
||||||
late String dialCode;
|
|
||||||
final _inviteFormKey = GlobalKey<FormState>();
|
final _inviteFormKey = GlobalKey<FormState>();
|
||||||
|
late Country _selectedCountry;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
dialCode = "+95";
|
_selectedCountry = Country(
|
||||||
|
name: 'Myanmar',
|
||||||
|
countryCode: 'MM',
|
||||||
|
displayName: 'Myanmar(MM)',
|
||||||
|
displayNameNoCountryCode: 'Myanmar',
|
||||||
|
e164Key: '',
|
||||||
|
e164Sc: -1,
|
||||||
|
example: '',
|
||||||
|
geographic: false,
|
||||||
|
level: -1,
|
||||||
|
phoneCode: '95');
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -47,6 +59,18 @@ class _InvitationCreateState extends State<InvitationCreate> {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
final phoneBox = InputPhone(
|
||||||
|
lableKey: "customer.phone",
|
||||||
|
validationLabel: "customer.phone_empty",
|
||||||
|
phoneCtl: _phoneController,
|
||||||
|
selectedCountry: _selectedCountry,
|
||||||
|
onValueChange: (country) {
|
||||||
|
setState(() {
|
||||||
|
_selectedCountry = country;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
return LocalProgress(
|
return LocalProgress(
|
||||||
inAsyncCall: _isLoading,
|
inAsyncCall: _isLoading,
|
||||||
child: Scaffold(
|
child: Scaffold(
|
||||||
@@ -73,76 +97,8 @@ class _InvitationCreateState extends State<InvitationCreate> {
|
|||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
nameBox,
|
nameBox,
|
||||||
SizedBox(height: 10),
|
SizedBox(height: 10),
|
||||||
Row(
|
phoneBox,
|
||||||
children: <Widget>[
|
SizedBox(height: 30),
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.all(8.0),
|
|
||||||
child: Icon(
|
|
||||||
Icons.phone,
|
|
||||||
color: primaryColor,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Container(
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
border:
|
|
||||||
Border.all(color: Colors.grey.shade400, width: 1),
|
|
||||||
borderRadius:
|
|
||||||
BorderRadius.all(Radius.circular(12.0))),
|
|
||||||
child: CountryCodePicker(
|
|
||||||
onChanged: _countryChange,
|
|
||||||
initialSelection: dialCode,
|
|
||||||
countryFilter: ['mm', 'us'],
|
|
||||||
showCountryOnly: false,
|
|
||||||
showOnlyCountryWhenClosed: false,
|
|
||||||
alignLeft: false,
|
|
||||||
textStyle:
|
|
||||||
TextStyle(fontSize: 16, color: Colors.black87),
|
|
||||||
searchDecoration: InputDecoration(
|
|
||||||
focusedBorder: UnderlineInputBorder(
|
|
||||||
borderSide: BorderSide(
|
|
||||||
color: Colors.black, width: 1.0))),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
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:
|
|
||||||
getLocalString(context, "customer.phone"),
|
|
||||||
labelStyle:
|
|
||||||
TextStyle(fontSize: 16, color: Colors.grey),
|
|
||||||
filled: true,
|
|
||||||
focusedBorder: UnderlineInputBorder(
|
|
||||||
borderSide: BorderSide(
|
|
||||||
color: Colors.grey, width: 1.0)),
|
|
||||||
errorStyle: TextStyle(
|
|
||||||
color: dangerColor,
|
|
||||||
)),
|
|
||||||
validator: (value) {
|
|
||||||
if (value == null || value.isEmpty) {
|
|
||||||
return "Please insert phone no";
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
},
|
|
||||||
autovalidateMode: AutovalidateMode.onUserInteraction,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
SizedBox(height: 20),
|
|
||||||
fcsButton(context, getLocalString(context, "invite.btn"),
|
fcsButton(context, getLocalString(context, "invite.btn"),
|
||||||
callack: _invite),
|
callack: _invite),
|
||||||
],
|
],
|
||||||
@@ -153,23 +109,21 @@ class _InvitationCreateState extends State<InvitationCreate> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
_countryChange(CountryCode countryCode) {
|
|
||||||
setState(() {
|
|
||||||
dialCode = countryCode.dialCode!;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
_invite() async {
|
_invite() async {
|
||||||
String userName = _nameController.text;
|
|
||||||
String phoneNumber = dialCode + _phoneController.text;
|
|
||||||
|
|
||||||
if (!_inviteFormKey.currentState!.validate()) {
|
if (!_inviteFormKey.currentState!.validate()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
setState(() {
|
setState(() {
|
||||||
_isLoading = true;
|
_isLoading = true;
|
||||||
});
|
});
|
||||||
try {
|
try {
|
||||||
|
String userName = _nameController.text;
|
||||||
|
|
||||||
|
bool isMyanmar = _selectedCountry.phoneCode == "95";
|
||||||
|
String dialCode = isMyanmar ? "+959" : "+${_selectedCountry.phoneCode}";
|
||||||
|
String phoneNumber = dialCode + _phoneController.text;
|
||||||
|
|
||||||
CustomerModel customerModel =
|
CustomerModel customerModel =
|
||||||
Provider.of<CustomerModel>(context, listen: false);
|
Provider.of<CustomerModel>(context, listen: false);
|
||||||
await customerModel.inviteUser(userName, phoneNumber);
|
await customerModel.inviteUser(userName, phoneNumber);
|
||||||
|
|||||||
@@ -153,8 +153,10 @@ class MainModel extends ChangeNotifier {
|
|||||||
return int.parse(packageInfo!.buildNumber) >= setting!.supportBuildNum;
|
return int.parse(packageInfo!.buildNumber) >= setting!.supportBuildNum;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<AuthResult> sendSms(String phoneNumber) {
|
Future<AuthResult> sendSms(String phoneNumber,
|
||||||
return Services.instance.authService.sendSmsCodeToPhoneNumber(phoneNumber);
|
{String? forceResendingToken}) {
|
||||||
|
return Services.instance.authService.sendSmsCodeToPhoneNumber(phoneNumber,
|
||||||
|
forceResendingToken: forceResendingToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<AuthResult> signin(String smsCode) async {
|
Future<AuthResult> signin(String smsCode) async {
|
||||||
|
|||||||
@@ -403,3 +403,12 @@ String removeTrailingZeros(double number) {
|
|||||||
: result;
|
: result;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool isValidEmail(String email) {
|
||||||
|
// Define a regular expression for validating an email
|
||||||
|
final emailRegex = RegExp(r'^[^@\s]+@[^@\s]+\.[^@\s]+$');
|
||||||
|
|
||||||
|
// Check if the email matches the pattern
|
||||||
|
return emailRegex.hasMatch(email);
|
||||||
|
}
|
||||||
114
lib/pages/profile/add_recovery_email.dart
Normal file
114
lib/pages/profile/add_recovery_email.dart
Normal file
@@ -0,0 +1,114 @@
|
|||||||
|
// ignore_for_file: use_build_context_synchronously
|
||||||
|
|
||||||
|
import 'package:flutter/cupertino.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
import '../../domain/entities/user.dart';
|
||||||
|
import '../../helpers/theme.dart';
|
||||||
|
import '../../localization/app_translations.dart';
|
||||||
|
import '../main/util.dart';
|
||||||
|
import '../widgets/input_text.dart';
|
||||||
|
import '../widgets/local_app_bar.dart';
|
||||||
|
import '../widgets/local_text.dart';
|
||||||
|
import '../widgets/progress.dart';
|
||||||
|
import 'confirm_recovery_email.dart';
|
||||||
|
|
||||||
|
class AddRecoveryEmail extends StatefulWidget {
|
||||||
|
final User user;
|
||||||
|
const AddRecoveryEmail({super.key, required this.user});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<AddRecoveryEmail> createState() => _AddRecoveryEmailState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _AddRecoveryEmailState extends State<AddRecoveryEmail> {
|
||||||
|
final _formKey = GlobalKey<FormState>();
|
||||||
|
bool _isLoading = false;
|
||||||
|
final TextEditingController _emailCtl = TextEditingController();
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
_emailCtl.text = widget.user.recoveryEmail ?? "";
|
||||||
|
super.initState();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final emailBox = InputText(
|
||||||
|
labelTextKey: "profile.email",
|
||||||
|
iconData: Icons.email_outlined,
|
||||||
|
controller: _emailCtl,
|
||||||
|
validator: (value) {
|
||||||
|
if (value == null || value.isEmpty) {
|
||||||
|
return AppTranslations.of(context)!.text('profile.email.empty');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isValidEmail(value)) {
|
||||||
|
return AppTranslations.of(context)!
|
||||||
|
.text('profile.email.mismatch_message');
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
final continueBtn = Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 30),
|
||||||
|
child: fcsButton(
|
||||||
|
context,
|
||||||
|
getLocalString(context, 'btn.continue'),
|
||||||
|
callack: _continue,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
return LocalProgress(
|
||||||
|
inAsyncCall: _isLoading,
|
||||||
|
child: Scaffold(
|
||||||
|
appBar: const LocalAppBar(
|
||||||
|
labelKey: 'profile.recovery_email.title',
|
||||||
|
backgroundColor: Colors.white,
|
||||||
|
labelColor: primaryColor,
|
||||||
|
arrowColor: primaryColor),
|
||||||
|
body: Form(
|
||||||
|
key: _formKey,
|
||||||
|
child: ListView(
|
||||||
|
padding: const EdgeInsets.only(left: 15, right: 15, top: 10),
|
||||||
|
children: [
|
||||||
|
LocalText(context, 'profile.email_instruction',
|
||||||
|
fontSize: 16, color: Colors.black),
|
||||||
|
const SizedBox(height: 15),
|
||||||
|
emailBox,
|
||||||
|
const SizedBox(height: 30),
|
||||||
|
continueBtn
|
||||||
|
],
|
||||||
|
)),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _continue() async {
|
||||||
|
if (_formKey.currentState != null && !_formKey.currentState!.validate()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setState(() {
|
||||||
|
_isLoading = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
try {
|
||||||
|
bool? updated = await Navigator.of(context, rootNavigator: true).push(
|
||||||
|
CupertinoPageRoute(
|
||||||
|
builder: (context) =>
|
||||||
|
ConfirmRecoveryEmail(email: _emailCtl.text)));
|
||||||
|
|
||||||
|
if (updated ?? false) {
|
||||||
|
Navigator.pop(context, true);
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
showMsgDialog(context, "Error", e.toString());
|
||||||
|
} finally {
|
||||||
|
setState(() {
|
||||||
|
_isLoading = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
142
lib/pages/profile/change_phone_number.dart
Normal file
142
lib/pages/profile/change_phone_number.dart
Normal file
@@ -0,0 +1,142 @@
|
|||||||
|
// ignore_for_file: use_build_context_synchronously
|
||||||
|
import 'package:country_picker/country_picker.dart';
|
||||||
|
import 'package:fcs/helpers/theme.dart';
|
||||||
|
import 'package:flutter/cupertino.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
|
import '../../domain/entities/auth_result.dart';
|
||||||
|
import '../../domain/entities/auth_status.dart';
|
||||||
|
import '../../domain/entities/user.dart';
|
||||||
|
import '../main/model/main_model.dart';
|
||||||
|
import '../main/util.dart';
|
||||||
|
import '../widgets/display_text.dart';
|
||||||
|
import '../widgets/input_phone.dart';
|
||||||
|
import '../widgets/local_app_bar.dart';
|
||||||
|
import '../widgets/progress.dart';
|
||||||
|
import 'confirm_phone_number.dart';
|
||||||
|
|
||||||
|
class ChangePhoneNumber extends StatefulWidget {
|
||||||
|
final User user;
|
||||||
|
const ChangePhoneNumber({super.key, required this.user});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<ChangePhoneNumber> createState() => _ChangePhoneNumberState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _ChangePhoneNumberState extends State<ChangePhoneNumber> {
|
||||||
|
bool _isLoading = false;
|
||||||
|
TextEditingController _newPhoneCtl = TextEditingController();
|
||||||
|
late Country _selectedCountry;
|
||||||
|
final _formKey = GlobalKey<FormState>();
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
_selectedCountry = Country(
|
||||||
|
name: 'Myanmar',
|
||||||
|
countryCode: 'MM',
|
||||||
|
displayName: 'Myanmar(MM)',
|
||||||
|
displayNameNoCountryCode: 'Myanmar',
|
||||||
|
e164Key: '',
|
||||||
|
e164Sc: -1,
|
||||||
|
example: '',
|
||||||
|
geographic: false,
|
||||||
|
level: -1,
|
||||||
|
phoneCode: '95');
|
||||||
|
super.initState();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final currentPhoneBox = DisplayText(
|
||||||
|
text: widget.user.phone,
|
||||||
|
labelTextKey: "profile.current_phone",
|
||||||
|
iconData: Icons.phone);
|
||||||
|
|
||||||
|
final newPhoneBox = InputPhone(
|
||||||
|
autofocus: true,
|
||||||
|
lableKey: "profile.new_phone",
|
||||||
|
validationLabel: "profile.new_phone_empty",
|
||||||
|
phoneCtl: _newPhoneCtl,
|
||||||
|
selectedCountry: _selectedCountry,
|
||||||
|
onValueChange: (country) {
|
||||||
|
setState(() {
|
||||||
|
_selectedCountry = country;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
final sendBtn = Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 30),
|
||||||
|
child: fcsButton(
|
||||||
|
context,
|
||||||
|
getLocalString(context, 'profile.send_sms'),
|
||||||
|
callack: _sendSMS,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
return Form(
|
||||||
|
key: _formKey,
|
||||||
|
child: LocalProgress(
|
||||||
|
inAsyncCall: _isLoading,
|
||||||
|
child: Scaffold(
|
||||||
|
appBar: const LocalAppBar(
|
||||||
|
labelKey: 'profile.change_phone.title',
|
||||||
|
backgroundColor: Colors.white,
|
||||||
|
labelColor: primaryColor,
|
||||||
|
arrowColor: primaryColor,
|
||||||
|
),
|
||||||
|
body: ListView(
|
||||||
|
padding: const EdgeInsets.only(left: 15, right: 15, top: 10),
|
||||||
|
children: [
|
||||||
|
currentPhoneBox,
|
||||||
|
const SizedBox(height: 15),
|
||||||
|
newPhoneBox,
|
||||||
|
const SizedBox(height: 30),
|
||||||
|
sendBtn
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _sendSMS() async {
|
||||||
|
if (_formKey.currentState != null && !_formKey.currentState!.validate()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (_newPhoneCtl.text.length < 5) {
|
||||||
|
showMsgDialog(context, "Error", "Invalid phone number");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setState(() {
|
||||||
|
_isLoading = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
try {
|
||||||
|
bool isMyanmar = _selectedCountry.phoneCode == "95";
|
||||||
|
String dialCode = isMyanmar ? "+959" : "+${_selectedCountry.phoneCode}";
|
||||||
|
String phoneNumber = dialCode + _newPhoneCtl.text;
|
||||||
|
|
||||||
|
AuthResult auth = await context.read<MainModel>().sendSms(phoneNumber);
|
||||||
|
if (auth.authStatus == AuthStatus.SMS_SENT) {
|
||||||
|
bool? updated = await Navigator.of(context, rootNavigator: true).push(
|
||||||
|
CupertinoPageRoute(
|
||||||
|
builder: (context) => ConfirmPhoneNumber(
|
||||||
|
phoneNumber: phoneNumber,
|
||||||
|
forceResendingToken: auth.forceResendingToken)));
|
||||||
|
if (updated ?? false) {
|
||||||
|
Navigator.pop(context, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
showMsgDialog(context, "Error", e.toString());
|
||||||
|
} finally {
|
||||||
|
setState(() {
|
||||||
|
_isLoading = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
232
lib/pages/profile/confirm_phone_number.dart
Normal file
232
lib/pages/profile/confirm_phone_number.dart
Normal file
@@ -0,0 +1,232 @@
|
|||||||
|
// ignore_for_file: use_build_context_synchronously
|
||||||
|
|
||||||
|
import 'dart:async';
|
||||||
|
|
||||||
|
import 'package:fcs/constants.dart';
|
||||||
|
import 'package:fcs/pages/widgets/local_app_bar.dart';
|
||||||
|
import 'package:fcs/pages/widgets/progress.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:pin_input_text_field/pin_input_text_field.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
|
import '../../domain/entities/auth_result.dart';
|
||||||
|
import '../../domain/entities/auth_status.dart';
|
||||||
|
import '../../helpers/theme.dart';
|
||||||
|
import '../main/model/main_model.dart';
|
||||||
|
import '../main/util.dart';
|
||||||
|
import '../widgets/local_text.dart';
|
||||||
|
|
||||||
|
class ConfirmPhoneNumber extends StatefulWidget {
|
||||||
|
final String phoneNumber;
|
||||||
|
final String? forceResendingToken;
|
||||||
|
const ConfirmPhoneNumber(
|
||||||
|
{super.key, required this.phoneNumber, this.forceResendingToken});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<ConfirmPhoneNumber> createState() => _ConfirmPhoneNumberState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _ConfirmPhoneNumberState extends State<ConfirmPhoneNumber> {
|
||||||
|
final _formKey = GlobalKey<FormState>();
|
||||||
|
bool _isLoading = false;
|
||||||
|
late String pin;
|
||||||
|
late bool allNumberEntered;
|
||||||
|
late Timer _timer;
|
||||||
|
int _start = resendCountSec;
|
||||||
|
bool canResend = false;
|
||||||
|
String? _forceResendingToken;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
pin = "";
|
||||||
|
allNumberEntered = false;
|
||||||
|
_forceResendingToken = widget.forceResendingToken;
|
||||||
|
super.initState();
|
||||||
|
startTimer();
|
||||||
|
}
|
||||||
|
|
||||||
|
void startTimer() {
|
||||||
|
_timer = Timer.periodic(
|
||||||
|
const Duration(seconds: 1),
|
||||||
|
(t) => setState(
|
||||||
|
() {
|
||||||
|
if (_start < 1) {
|
||||||
|
t.cancel();
|
||||||
|
canResend = true;
|
||||||
|
} else {
|
||||||
|
_start = _start - 1;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
_timer.cancel();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
bool isMyanmar = widget.phoneNumber.startsWith("+959");
|
||||||
|
|
||||||
|
return LocalProgress(
|
||||||
|
inAsyncCall: _isLoading,
|
||||||
|
child: Scaffold(
|
||||||
|
appBar: const LocalAppBar(
|
||||||
|
labelKey: 'profile.confirm_new_phone.title',
|
||||||
|
backgroundColor: Colors.white,
|
||||||
|
labelColor: primaryColor,
|
||||||
|
arrowColor: primaryColor),
|
||||||
|
body: Form(
|
||||||
|
key: _formKey,
|
||||||
|
child: ListView(
|
||||||
|
padding: const EdgeInsets.only(left: 15, right: 15, top: 10),
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
padding: const EdgeInsets.only(top: 40),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Flexible(
|
||||||
|
child: LocalText(context, "sms.six.digit",
|
||||||
|
fontSize: 16, color: labelColor),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
widget.phoneNumber.startsWith("+959")
|
||||||
|
? "0${widget.phoneNumber.substring(3)}"
|
||||||
|
: widget.phoneNumber,
|
||||||
|
style: const TextStyle(color: primaryColor, fontSize: 16),
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
height: 30,
|
||||||
|
),
|
||||||
|
LocalText(context, "sms.code", color: labelColor, fontSize: 16),
|
||||||
|
Container(
|
||||||
|
padding: const EdgeInsets.only(top: 10),
|
||||||
|
child: PinInputTextField(
|
||||||
|
pinLength: 6,
|
||||||
|
cursor: Cursor(
|
||||||
|
color: primaryColor,
|
||||||
|
enabled: true,
|
||||||
|
width: 2,
|
||||||
|
height: 23),
|
||||||
|
decoration: BoxLooseDecoration(
|
||||||
|
textStyle: TextStyle(
|
||||||
|
color:
|
||||||
|
Theme.of(context).textTheme.labelMedium!.color,
|
||||||
|
fontSize: 20),
|
||||||
|
strokeColorBuilder:
|
||||||
|
const FixedColorBuilder(labelColor)),
|
||||||
|
textInputAction: TextInputAction.done,
|
||||||
|
autoFocus: true,
|
||||||
|
onChanged: _pinChange,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 40),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 30),
|
||||||
|
child: fcsButton(
|
||||||
|
context,
|
||||||
|
getLocalString(context, 'profile.change_phone.btn'),
|
||||||
|
callack: allNumberEntered
|
||||||
|
? () {
|
||||||
|
_change();
|
||||||
|
}
|
||||||
|
: null,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 30),
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: <Widget>[
|
||||||
|
ElevatedButton(
|
||||||
|
style: ElevatedButton.styleFrom(
|
||||||
|
backgroundColor:
|
||||||
|
canResend ? Colors.white : Colors.grey,
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(8.0),
|
||||||
|
side: BorderSide(
|
||||||
|
color: canResend
|
||||||
|
? primaryColor
|
||||||
|
: Colors.grey.shade400))),
|
||||||
|
onPressed: canResend
|
||||||
|
? () {
|
||||||
|
_resend(isMyanmar);
|
||||||
|
}
|
||||||
|
: null,
|
||||||
|
child: LocalText(context, "sms.resend",
|
||||||
|
color:
|
||||||
|
canResend ? primaryColor : Colors.grey.shade400,
|
||||||
|
fontSize: 16),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Row(
|
||||||
|
children: <Widget>[
|
||||||
|
LocalText(context, 'sms.resend.seconds',
|
||||||
|
fontSize: 15,
|
||||||
|
translationVariables: [_start.toString()],
|
||||||
|
color: primaryColor),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
const SizedBox(height: 20),
|
||||||
|
],
|
||||||
|
)),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
_pinChange(pin) {
|
||||||
|
setState(() {
|
||||||
|
this.pin = pin;
|
||||||
|
allNumberEntered = this.pin.length == 6;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
_resend(bool isMyanmar) async {
|
||||||
|
try {
|
||||||
|
setState(() {
|
||||||
|
_start = resendCountSec;
|
||||||
|
canResend = false;
|
||||||
|
});
|
||||||
|
|
||||||
|
_timer.cancel();
|
||||||
|
startTimer();
|
||||||
|
|
||||||
|
var mainModel = context.read<MainModel>();
|
||||||
|
|
||||||
|
AuthResult auth = await mainModel.sendSms(widget.phoneNumber,
|
||||||
|
forceResendingToken: _forceResendingToken);
|
||||||
|
|
||||||
|
if (auth.authStatus == AuthStatus.SMS_SENT) {
|
||||||
|
_forceResendingToken = auth.forceResendingToken;
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
await showMsgDialog(context, "Error", e.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_change() async {
|
||||||
|
setState(() {
|
||||||
|
_isLoading = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
try {
|
||||||
|
// var mainModel = context.read<MainModel>();
|
||||||
|
// await mainModel.updatePhoneNumber(pin);
|
||||||
|
Navigator.pop(context, true);
|
||||||
|
} catch (e) {
|
||||||
|
await showMsgDialog(context, "Error", e.toString());
|
||||||
|
} finally {
|
||||||
|
if (mounted) {
|
||||||
|
setState(() {
|
||||||
|
_isLoading = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
138
lib/pages/profile/confirm_recovery_email.dart
Normal file
138
lib/pages/profile/confirm_recovery_email.dart
Normal file
@@ -0,0 +1,138 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:pin_input_text_field/pin_input_text_field.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
|
import '../../helpers/theme.dart';
|
||||||
|
import '../../localization/app_translations.dart';
|
||||||
|
import '../main/model/language_model.dart';
|
||||||
|
import '../main/util.dart';
|
||||||
|
import '../widgets/local_app_bar.dart';
|
||||||
|
import '../widgets/local_text.dart';
|
||||||
|
import '../widgets/progress.dart';
|
||||||
|
|
||||||
|
class ConfirmRecoveryEmail extends StatefulWidget {
|
||||||
|
final String email;
|
||||||
|
const ConfirmRecoveryEmail({super.key, required this.email});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<ConfirmRecoveryEmail> createState() => _ConfirmRecoveryEmailState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _ConfirmRecoveryEmailState extends State<ConfirmRecoveryEmail> {
|
||||||
|
bool _isLoading = false;
|
||||||
|
late String pin;
|
||||||
|
late bool allNumberEntered;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
pin = "";
|
||||||
|
allNumberEntered = false;
|
||||||
|
super.initState();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
var isEng = context.watch<LanguageModel>().isEng;
|
||||||
|
|
||||||
|
return LocalProgress(
|
||||||
|
inAsyncCall: _isLoading,
|
||||||
|
child: Scaffold(
|
||||||
|
appBar: const LocalAppBar(
|
||||||
|
labelKey: 'profile.comfirm_email.title',
|
||||||
|
backgroundColor: Colors.white,
|
||||||
|
labelColor: primaryColor,
|
||||||
|
arrowColor: primaryColor),
|
||||||
|
body: ListView(
|
||||||
|
padding: const EdgeInsets.only(left: 15, right: 15, top: 20),
|
||||||
|
children: [
|
||||||
|
RichText(
|
||||||
|
text: TextSpan(children: [
|
||||||
|
TextSpan(
|
||||||
|
text: AppTranslations.of(context)!
|
||||||
|
.text("profile.confirm_email.send_to"),
|
||||||
|
style: isEng
|
||||||
|
? newLabelStyle(
|
||||||
|
fontWeight: FontWeight.normal,
|
||||||
|
color:
|
||||||
|
labelColor,
|
||||||
|
fontSize: 16)
|
||||||
|
: newLabelStyleMM(
|
||||||
|
fontWeight: FontWeight.normal,
|
||||||
|
color:
|
||||||
|
labelColor,
|
||||||
|
fontSize: 16)),
|
||||||
|
TextSpan(
|
||||||
|
text: " ${widget.email}",
|
||||||
|
style: const TextStyle(fontSize: 16, color: primaryColor))
|
||||||
|
]),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 40),
|
||||||
|
LocalText(
|
||||||
|
context,
|
||||||
|
'profile.confirm_email.insruction',
|
||||||
|
fontSize: 16,
|
||||||
|
color: labelColor,
|
||||||
|
fontWeight: FontWeight.normal,
|
||||||
|
),
|
||||||
|
const SizedBox(height: 40),
|
||||||
|
LocalText(context, "sms.code",
|
||||||
|
color: labelColor, fontSize: 16),
|
||||||
|
Container(
|
||||||
|
padding: const EdgeInsets.only(top: 10),
|
||||||
|
child: PinInputTextField(
|
||||||
|
pinLength: 6,
|
||||||
|
cursor: Cursor(
|
||||||
|
color: primaryColor, enabled: true, width: 2, height: 23),
|
||||||
|
decoration: BoxLooseDecoration(
|
||||||
|
textStyle: TextStyle(
|
||||||
|
color: Theme.of(context).textTheme.labelMedium!.color,
|
||||||
|
fontSize: 20),
|
||||||
|
strokeColorBuilder: const FixedColorBuilder(labelColor)),
|
||||||
|
textInputAction: TextInputAction.done,
|
||||||
|
autoFocus: true,
|
||||||
|
onChanged: _pinChange,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 40),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 30),
|
||||||
|
child: fcsButton(
|
||||||
|
context,
|
||||||
|
getLocalString(context, 'btn.confirm'),
|
||||||
|
callack: allNumberEntered
|
||||||
|
? () {
|
||||||
|
_confirm();
|
||||||
|
}
|
||||||
|
: null,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
_pinChange(pin) {
|
||||||
|
setState(() {
|
||||||
|
this.pin = pin;
|
||||||
|
allNumberEntered = this.pin.length == 6;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
_confirm() async {
|
||||||
|
setState(() {
|
||||||
|
_isLoading = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
try {
|
||||||
|
Navigator.pop(context, true);
|
||||||
|
} catch (e) {
|
||||||
|
// ignore: use_build_context_synchronously
|
||||||
|
await showMsgDialog(context, "Error", e.toString());
|
||||||
|
} finally {
|
||||||
|
setState(() {
|
||||||
|
_isLoading = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -25,6 +25,8 @@ import '../../helpers/theme.dart';
|
|||||||
import 'package:collection/collection.dart';
|
import 'package:collection/collection.dart';
|
||||||
|
|
||||||
import 'account_delection_page.dart';
|
import 'account_delection_page.dart';
|
||||||
|
import 'add_recovery_email.dart';
|
||||||
|
import 'change_phone_number.dart';
|
||||||
|
|
||||||
typedef void ProfileCallback();
|
typedef void ProfileCallback();
|
||||||
|
|
||||||
@@ -69,44 +71,70 @@ class _ProfileState extends State<Profile> {
|
|||||||
if (mainModel.user == null) {
|
if (mainModel.user == null) {
|
||||||
return Container();
|
return Container();
|
||||||
}
|
}
|
||||||
|
User user = mainModel.user!;
|
||||||
|
|
||||||
buildLanguage(languageModel);
|
buildLanguage(languageModel);
|
||||||
DeliveryAddressModel deliveryAddressModel =
|
var deliveryAddressModel = Provider.of<DeliveryAddressModel>(context);
|
||||||
Provider.of<DeliveryAddressModel>(context);
|
|
||||||
|
|
||||||
final namebox = DisplayText(
|
final namebox = DisplayText(
|
||||||
text: "${mainModel.user!.name ?? ''}" +
|
text: "${user.name ?? ''}" + " (${user.status ?? ''})",
|
||||||
" (${mainModel.user!.status ?? ''})",
|
|
||||||
labelTextKey: "profile.name",
|
labelTextKey: "profile.name",
|
||||||
iconData: Icons.person,
|
iconData: Icons.person,
|
||||||
);
|
);
|
||||||
final currencyBox = DisplayText(
|
|
||||||
text: mainModel.user!.preferCurrency ?? "",
|
final currencyBox = Row(
|
||||||
labelTextKey: "profile.currency",
|
children: <Widget>[
|
||||||
iconData: FontAwesome5Regular.money_bill_alt,
|
Expanded(
|
||||||
|
child: DisplayText(
|
||||||
|
text: user.preferCurrency ?? "",
|
||||||
|
labelTextKey: "profile.currency",
|
||||||
|
iconData: FontAwesome5Regular.money_bill_alt,
|
||||||
|
)),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(right: 0),
|
||||||
|
child: IconButton(
|
||||||
|
icon: Icon(Icons.edit, color: Colors.grey),
|
||||||
|
onPressed: _editCurrency),
|
||||||
|
)
|
||||||
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
final deleteAccountBox = DisplayText(
|
final deleteAccountBox = DisplayText(
|
||||||
labelTextKey: "profile.delete.title",
|
labelTextKey: "profile.delete.title",
|
||||||
iconData: MaterialCommunityIcons.account_remove,
|
iconData: MaterialCommunityIcons.account_remove,
|
||||||
);
|
);
|
||||||
|
|
||||||
final phonenumberbox = DisplayText(
|
final phonenumberBox = Row(
|
||||||
text: mainModel.user!.phone,
|
children: [
|
||||||
labelTextKey: "profile.phone",
|
Expanded(
|
||||||
iconData: Icons.phone,
|
child: DisplayText(
|
||||||
|
text: user.phone,
|
||||||
|
labelTextKey: "profile.phone",
|
||||||
|
iconData: Icons.phone),
|
||||||
|
),
|
||||||
|
IconButton(
|
||||||
|
icon: Icon(Icons.edit, color: Colors.grey),
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.of(context, rootNavigator: true).push(
|
||||||
|
CupertinoPageRoute(
|
||||||
|
builder: (context) => ChangePhoneNumber(user: user)));
|
||||||
|
})
|
||||||
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
final fcsIDBox = Row(
|
final fcsIDBox = Row(
|
||||||
children: [
|
children: [
|
||||||
Expanded(
|
Expanded(
|
||||||
child: DisplayText(
|
child: DisplayText(
|
||||||
text: mainModel.user!.fcsID ?? "",
|
text: user.fcsID ?? "",
|
||||||
labelTextKey: "customer.fcs.id",
|
labelTextKey: "customer.fcs.id",
|
||||||
icon: FcsIDIcon(),
|
icon: FcsIDIcon(),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
IconButton(
|
IconButton(
|
||||||
icon: Icon(Icons.content_copy, color: Colors.grey),
|
icon: Icon(Icons.content_copy, color: Colors.grey),
|
||||||
onPressed: () => _copy(getLocalString(context, "customer.fcs.id"),
|
onPressed: () => _copy(
|
||||||
mainModel.user!.fcsID ?? ""),
|
getLocalString(context, "customer.fcs.id"), user.fcsID ?? ""),
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
@@ -141,6 +169,22 @@ class _ProfileState extends State<Profile> {
|
|||||||
},
|
},
|
||||||
iconData: Icons.exit_to_app);
|
iconData: Icons.exit_to_app);
|
||||||
|
|
||||||
|
final emailBox = Row(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: DisplayText(
|
||||||
|
text: user.recoveryEmail,
|
||||||
|
labelTextKey: "profile.recovery.email",
|
||||||
|
iconData: Icons.email_outlined,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
IconButton(icon: Icon(Icons.edit, color: Colors.grey), onPressed: () {
|
||||||
|
Navigator.of(context, rootNavigator: true).push(
|
||||||
|
CupertinoPageRoute(
|
||||||
|
builder: (context) => AddRecoveryEmail(user: user)));
|
||||||
|
})
|
||||||
|
],
|
||||||
|
);
|
||||||
return LocalProgress(
|
return LocalProgress(
|
||||||
inAsyncCall: _isLoading,
|
inAsyncCall: _isLoading,
|
||||||
child: Scaffold(
|
child: Scaffold(
|
||||||
@@ -165,20 +209,11 @@ class _ProfileState extends State<Profile> {
|
|||||||
)
|
)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
phonenumberbox,
|
phonenumberBox,
|
||||||
fcsIDBox,
|
fcsIDBox,
|
||||||
usaShippingAddressBox,
|
usaShippingAddressBox,
|
||||||
Row(
|
currencyBox,
|
||||||
children: <Widget>[
|
emailBox,
|
||||||
Expanded(child: currencyBox),
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.only(right: 0),
|
|
||||||
child: IconButton(
|
|
||||||
icon: Icon(Icons.edit, color: Colors.grey),
|
|
||||||
onPressed: _editCurrency),
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
DefaultDeliveryAddress(
|
DefaultDeliveryAddress(
|
||||||
labelKey: "profile.default.delivery.address",
|
labelKey: "profile.default.delivery.address",
|
||||||
deliveryAddress: deliveryAddressModel.defalutAddress,
|
deliveryAddress: deliveryAddressModel.defalutAddress,
|
||||||
@@ -298,20 +333,22 @@ class _ProfileState extends State<Profile> {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return Column(
|
return privileges.isEmpty
|
||||||
children: <Widget>[
|
? const SizedBox()
|
||||||
DisplayText(
|
: Column(
|
||||||
labelTextKey: "profile.privileges",
|
children: <Widget>[
|
||||||
iconData: MaterialCommunityIcons.clipboard_check_outline,
|
DisplayText(
|
||||||
),
|
labelTextKey: "profile.privileges",
|
||||||
Padding(
|
iconData: MaterialCommunityIcons.clipboard_check_outline,
|
||||||
padding: const EdgeInsets.only(left: 30.0),
|
),
|
||||||
child: Column(
|
Padding(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
padding: const EdgeInsets.only(left: 30.0),
|
||||||
children: getRowPrivilegeWidget(privileges)),
|
child: Column(
|
||||||
)
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
],
|
children: getRowPrivilegeWidget(privileges)),
|
||||||
);
|
)
|
||||||
|
],
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Widget> getRowPrivilegeWidget(List<Privilege> privileges) {
|
List<Widget> getRowPrivilegeWidget(List<Privilege> privileges) {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import 'package:country_code_picker/country_code_picker.dart';
|
import 'package:country_picker/country_picker.dart';
|
||||||
import 'package:fcs/domain/entities/auth_result.dart';
|
import 'package:fcs/domain/entities/auth_result.dart';
|
||||||
import 'package:fcs/domain/entities/auth_status.dart';
|
import 'package:fcs/domain/entities/auth_status.dart';
|
||||||
import 'package:fcs/pages/main/model/main_model.dart';
|
import 'package:fcs/pages/main/model/main_model.dart';
|
||||||
@@ -13,6 +13,7 @@ import 'package:provider/provider.dart';
|
|||||||
|
|
||||||
import '../../helpers/theme.dart';
|
import '../../helpers/theme.dart';
|
||||||
import '../main/util.dart';
|
import '../main/util.dart';
|
||||||
|
import '../widgets/input_phone.dart';
|
||||||
import 'sms_code_page.dart';
|
import 'sms_code_page.dart';
|
||||||
|
|
||||||
class SigninPage extends StatefulWidget {
|
class SigninPage extends StatefulWidget {
|
||||||
@@ -25,15 +26,22 @@ class _SigninPageState extends State<SigninPage> {
|
|||||||
late String dialCode;
|
late String dialCode;
|
||||||
|
|
||||||
TextEditingController phonenumberCtl = new TextEditingController();
|
TextEditingController phonenumberCtl = new TextEditingController();
|
||||||
|
late Country _selectedCountry;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
phonenumberCtl = new TextEditingController(text: "09");
|
_selectedCountry = Country(
|
||||||
phonenumberCtl.selection = TextSelection.fromPosition(
|
name: 'Myanmar',
|
||||||
TextPosition(offset: phonenumberCtl.text.length));
|
countryCode: 'MM',
|
||||||
|
displayName: 'Myanmar(MM)',
|
||||||
dialCode = "+95";
|
displayNameNoCountryCode: 'Myanmar',
|
||||||
|
e164Key: '',
|
||||||
|
e164Sc: -1,
|
||||||
|
example: '',
|
||||||
|
geographic: false,
|
||||||
|
level: -1,
|
||||||
|
phoneCode: '95');
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -67,53 +75,16 @@ class _SigninPageState extends State<SigninPage> {
|
|||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Row(
|
InputPhone(
|
||||||
children: <Widget>[
|
autofocus: true,
|
||||||
Container(
|
validationLabel: "login.phone_empty",
|
||||||
decoration: BoxDecoration(
|
phoneCtl: phonenumberCtl,
|
||||||
border: Border.all(color: Colors.grey.shade400, width: 1),
|
selectedCountry: _selectedCountry,
|
||||||
borderRadius: BorderRadius.all(Radius.circular(12.0))),
|
onValueChange: (country) {
|
||||||
child: CountryCodePicker(
|
setState(() {
|
||||||
onChanged: _countryChange,
|
_selectedCountry = country;
|
||||||
initialSelection: dialCode,
|
});
|
||||||
countryFilter: ['mm', 'us'],
|
},
|
||||||
showCountryOnly: false,
|
|
||||||
showOnlyCountryWhenClosed: false,
|
|
||||||
alignLeft: false,
|
|
||||||
textStyle: TextStyle(fontSize: 16, color: Colors.black87),
|
|
||||||
searchDecoration: InputDecoration(
|
|
||||||
focusedBorder: UnderlineInputBorder(
|
|
||||||
borderSide:
|
|
||||||
BorderSide(color: Colors.black, width: 1.0)))),
|
|
||||||
),
|
|
||||||
SizedBox(
|
|
||||||
width: 10,
|
|
||||||
),
|
|
||||||
Flexible(
|
|
||||||
child: Container(
|
|
||||||
padding: EdgeInsets.only(top: 10, bottom: 10),
|
|
||||||
child: TextFormField(
|
|
||||||
controller: phonenumberCtl,
|
|
||||||
cursorColor: primaryColor,
|
|
||||||
textAlign: TextAlign.left,
|
|
||||||
autofocus: true,
|
|
||||||
keyboardType: TextInputType.phone,
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 18,
|
|
||||||
),
|
|
||||||
decoration: new InputDecoration(
|
|
||||||
contentPadding: EdgeInsets.only(top: 8),
|
|
||||||
enabledBorder: UnderlineInputBorder(
|
|
||||||
borderSide:
|
|
||||||
BorderSide(color: primaryColor, width: 1.0)),
|
|
||||||
focusedBorder: UnderlineInputBorder(
|
|
||||||
borderSide:
|
|
||||||
BorderSide(color: primaryColor, width: 1.0)),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
SizedBox(
|
SizedBox(
|
||||||
height: 20,
|
height: 20,
|
||||||
@@ -140,15 +111,8 @@ class _SigninPageState extends State<SigninPage> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
_countryChange(CountryCode countryCode) {
|
|
||||||
setState(() {
|
|
||||||
dialCode = countryCode.dialCode ?? '+95';
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
_next() async {
|
_next() async {
|
||||||
String phoneNumber = phonenumberCtl.text;
|
if (phonenumberCtl.text.length < 5) {
|
||||||
if (phoneNumber.length < 5) {
|
|
||||||
showMsgDialog(context, "Error", "Invalid phone number");
|
showMsgDialog(context, "Error", "Invalid phone number");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -157,16 +121,17 @@ class _SigninPageState extends State<SigninPage> {
|
|||||||
_isLoading = true;
|
_isLoading = true;
|
||||||
});
|
});
|
||||||
|
|
||||||
try {
|
bool isMyanmar = _selectedCountry.phoneCode == "95";
|
||||||
phoneNumber = phoneNumber[0] == "0"
|
String dialCode = isMyanmar ? "+959" : "+${_selectedCountry.phoneCode}";
|
||||||
? phoneNumber.replaceFirst("0", "")
|
|
||||||
: phoneNumber;
|
|
||||||
phoneNumber = dialCode + phoneNumber;
|
|
||||||
|
|
||||||
|
try {
|
||||||
|
String phoneNumber = dialCode + phonenumberCtl.text;
|
||||||
AuthResult auth = await context.read<MainModel>().sendSms(phoneNumber);
|
AuthResult auth = await context.read<MainModel>().sendSms(phoneNumber);
|
||||||
if (auth.authStatus == AuthStatus.SMS_SENT) {
|
if (auth.authStatus == AuthStatus.SMS_SENT) {
|
||||||
await Navigator.of(context).push(CupertinoPageRoute(
|
await Navigator.of(context).push(CupertinoPageRoute(
|
||||||
builder: (context) => SmsCodePage(phoneNumber: phoneNumber)));
|
builder: (context) => SmsCodePage(
|
||||||
|
phoneNumber: phoneNumber,
|
||||||
|
forceResendingToken: auth.forceResendingToken)));
|
||||||
Navigator.pop(context);
|
Navigator.pop(context);
|
||||||
} else if (auth.authStatus == AuthStatus.AUTH_VERIFIED) {
|
} else if (auth.authStatus == AuthStatus.AUTH_VERIFIED) {
|
||||||
await navigateAfterAuthVerified(context);
|
await navigateAfterAuthVerified(context);
|
||||||
|
|||||||
@@ -12,13 +12,15 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:pin_input_text_field/pin_input_text_field.dart';
|
import 'package:pin_input_text_field/pin_input_text_field.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
|
import '../../constants.dart';
|
||||||
import '../../helpers/theme.dart';
|
import '../../helpers/theme.dart';
|
||||||
|
|
||||||
const resend_count_sec = 30;
|
|
||||||
|
|
||||||
class SmsCodePage extends StatefulWidget {
|
class SmsCodePage extends StatefulWidget {
|
||||||
final String phoneNumber;
|
final String phoneNumber;
|
||||||
const SmsCodePage({Key? key, required this.phoneNumber}) : super(key: key);
|
final String? forceResendingToken;
|
||||||
|
const SmsCodePage(
|
||||||
|
{Key? key, required this.phoneNumber, this.forceResendingToken})
|
||||||
|
: super(key: key);
|
||||||
@override
|
@override
|
||||||
_SmsCodePageState createState() => _SmsCodePageState();
|
_SmsCodePageState createState() => _SmsCodePageState();
|
||||||
}
|
}
|
||||||
@@ -26,16 +28,18 @@ class SmsCodePage extends StatefulWidget {
|
|||||||
class _SmsCodePageState extends State<SmsCodePage> {
|
class _SmsCodePageState extends State<SmsCodePage> {
|
||||||
bool _isLoading = false;
|
bool _isLoading = false;
|
||||||
bool canResend = false;
|
bool canResend = false;
|
||||||
int _start = resend_count_sec;
|
int _start = resendCountSec;
|
||||||
|
|
||||||
late String pin;
|
late String pin;
|
||||||
late bool allNumberEntered;
|
late bool allNumberEntered;
|
||||||
late Timer _timer;
|
late Timer _timer;
|
||||||
|
String? _forceResendingToken;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
pin = "";
|
pin = "";
|
||||||
allNumberEntered = false;
|
allNumberEntered = false;
|
||||||
|
_forceResendingToken = widget.forceResendingToken;
|
||||||
super.initState();
|
super.initState();
|
||||||
startTimer();
|
startTimer();
|
||||||
}
|
}
|
||||||
@@ -186,7 +190,28 @@ class _SmsCodePageState extends State<SmsCodePage> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
_resend() async {}
|
_resend() async {
|
||||||
|
try {
|
||||||
|
setState(() {
|
||||||
|
_start = resendCountSec;
|
||||||
|
canResend = false;
|
||||||
|
});
|
||||||
|
|
||||||
|
_timer.cancel();
|
||||||
|
startTimer();
|
||||||
|
|
||||||
|
var mainModel = context.read<MainModel>();
|
||||||
|
|
||||||
|
AuthResult auth = await mainModel.sendSms(widget.phoneNumber,
|
||||||
|
forceResendingToken: _forceResendingToken);
|
||||||
|
|
||||||
|
if (auth.authStatus == AuthStatus.SMS_SENT) {
|
||||||
|
_forceResendingToken = auth.forceResendingToken;
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
await showMsgDialog(context, "Error", e.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
_verify() async {
|
_verify() async {
|
||||||
setState(() {
|
setState(() {
|
||||||
|
|||||||
188
lib/pages/widgets/input_phone.dart
Normal file
188
lib/pages/widgets/input_phone.dart
Normal file
@@ -0,0 +1,188 @@
|
|||||||
|
import 'package:fcs/helpers/theme.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:country_picker/country_picker.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
|
import '../../localization/app_translations.dart';
|
||||||
|
import '../main/model/language_model.dart';
|
||||||
|
|
||||||
|
typedef OnValueChange = Function(Country country);
|
||||||
|
|
||||||
|
class InputPhone extends StatefulWidget {
|
||||||
|
final String? lableKey;
|
||||||
|
final String? validationLabel;
|
||||||
|
final OnValueChange onValueChange;
|
||||||
|
final Country selectedCountry;
|
||||||
|
final TextEditingController phoneCtl;
|
||||||
|
final Function(String)? onInputChanged;
|
||||||
|
final bool autofocus;
|
||||||
|
|
||||||
|
const InputPhone(
|
||||||
|
{super.key,
|
||||||
|
this.lableKey,
|
||||||
|
required this.onValueChange,
|
||||||
|
required this.selectedCountry,
|
||||||
|
this.onInputChanged,
|
||||||
|
required this.phoneCtl,
|
||||||
|
this.validationLabel,
|
||||||
|
this.autofocus = false});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<InputPhone> createState() => _InputPhoneState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _InputPhoneState extends State<InputPhone> {
|
||||||
|
List<String>? signinCountries = [];
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
init();
|
||||||
|
super.initState();
|
||||||
|
}
|
||||||
|
|
||||||
|
init() {
|
||||||
|
List<String>? countries = ['mm', 'us'];
|
||||||
|
|
||||||
|
for (var c in countries) {
|
||||||
|
setState(() {
|
||||||
|
signinCountries?.add(c.toUpperCase());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
bool isMyanmar = widget.selectedCountry.phoneCode == "95";
|
||||||
|
var languageModel = Provider.of<LanguageModel>(context);
|
||||||
|
|
||||||
|
return Padding(
|
||||||
|
padding: const EdgeInsets.only(top: 10),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
GestureDetector(
|
||||||
|
onTap: () {
|
||||||
|
showCountryPicker(
|
||||||
|
context: context,
|
||||||
|
countryFilter: signinCountries,
|
||||||
|
showPhoneCode: true,
|
||||||
|
showSearch: true,
|
||||||
|
countryListTheme: const CountryListThemeData(
|
||||||
|
flagSize: 25,
|
||||||
|
backgroundColor: Colors.white,
|
||||||
|
textStyle: TextStyle(fontSize: 15, color: Colors.black),
|
||||||
|
bottomSheetHeight: 500,
|
||||||
|
borderRadius: BorderRadius.only(
|
||||||
|
topLeft: Radius.circular(20.0),
|
||||||
|
topRight: Radius.circular(20.0),
|
||||||
|
),
|
||||||
|
inputDecoration: InputDecoration(
|
||||||
|
labelText: 'Search',
|
||||||
|
labelStyle: TextStyle(color: Colors.black),
|
||||||
|
floatingLabelStyle: TextStyle(color: Colors.black),
|
||||||
|
hintText: 'Search',
|
||||||
|
hintStyle: TextStyle(color: Colors.black),
|
||||||
|
hintMaxLines: 1,
|
||||||
|
prefixIcon: Icon(Icons.search, color: Colors.black),
|
||||||
|
border: OutlineInputBorder(),
|
||||||
|
enabledBorder: OutlineInputBorder(
|
||||||
|
borderSide:
|
||||||
|
BorderSide(width: 1, color: Colors.black)),
|
||||||
|
focusedBorder: OutlineInputBorder(
|
||||||
|
borderRadius:
|
||||||
|
BorderRadius.all(Radius.circular(5.0)),
|
||||||
|
borderSide: BorderSide(color: Colors.black)),
|
||||||
|
),
|
||||||
|
searchTextStyle: TextStyle(color: Colors.black)),
|
||||||
|
onSelect: (Country country) {
|
||||||
|
widget.onValueChange(country);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
width: 95,
|
||||||
|
padding: const EdgeInsets.only(
|
||||||
|
left: 5, bottom: 12, right: 5, top: 12),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
border: Border.all(color: Colors.grey.shade400),
|
||||||
|
borderRadius: BorderRadius.circular(5),
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
padding: const EdgeInsets.fromLTRB(0, 0, 5, 0),
|
||||||
|
child: Text(widget.selectedCountry.flagEmoji)),
|
||||||
|
Text(
|
||||||
|
isMyanmar
|
||||||
|
? "+95"
|
||||||
|
: "+${widget.selectedCountry.phoneCode}",
|
||||||
|
style: const TextStyle(
|
||||||
|
fontSize: 16, color: Colors.black),
|
||||||
|
),
|
||||||
|
const Icon(Icons.arrow_drop_down),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(width: 5),
|
||||||
|
Flexible(
|
||||||
|
child: Container(
|
||||||
|
padding: const EdgeInsets.only(left: 10),
|
||||||
|
child: TextFormField(
|
||||||
|
autofocus: widget.autofocus,
|
||||||
|
keyboardType: TextInputType.phone,
|
||||||
|
onChanged: widget.onInputChanged,
|
||||||
|
controller: widget.phoneCtl,
|
||||||
|
maxLines: 1,
|
||||||
|
cursorColor: primaryColor,
|
||||||
|
style: const TextStyle(fontSize: 16, color: Colors.black),
|
||||||
|
decoration: InputDecoration(
|
||||||
|
labelStyle: languageModel.isEng
|
||||||
|
? newLabelStyle(color: Colors.black54, fontSize: 20)
|
||||||
|
: newLabelStyleMM(
|
||||||
|
color: Colors.black54, fontSize: 20),
|
||||||
|
labelText: widget.lableKey != null
|
||||||
|
? AppTranslations.of(context)!
|
||||||
|
.text(widget.lableKey!)
|
||||||
|
: null,
|
||||||
|
hintStyle: const TextStyle(color: Color(0xFFBBBBBB)),
|
||||||
|
errorStyle: const TextStyle(color: dangerColor),
|
||||||
|
prefix: Padding(
|
||||||
|
padding: EdgeInsets.only(left: isMyanmar ? 0 : 13),
|
||||||
|
child: Text(isMyanmar ? "9 " : "",
|
||||||
|
style: const TextStyle(color: Colors.black))),
|
||||||
|
enabledBorder: const UnderlineInputBorder(
|
||||||
|
borderSide:
|
||||||
|
BorderSide(color: primaryColor, width: 1.0)),
|
||||||
|
focusedBorder: const UnderlineInputBorder(
|
||||||
|
borderSide:
|
||||||
|
BorderSide(color: primaryColor, width: 1.0)),
|
||||||
|
errorBorder: null,
|
||||||
|
focusedErrorBorder: null),
|
||||||
|
validator: (value) {
|
||||||
|
if (value!.isEmpty) {
|
||||||
|
if (widget.validationLabel == null) return null;
|
||||||
|
return AppTranslations.of(context)!
|
||||||
|
.text(widget.validationLabel!);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -42,7 +42,6 @@ dependencies:
|
|||||||
connectivity_plus: ^6.1.0
|
connectivity_plus: ^6.1.0
|
||||||
logging: ^1.0.1
|
logging: ^1.0.1
|
||||||
permission_handler: ^11.1.0
|
permission_handler: ^11.1.0
|
||||||
country_code_picker: ^3.0.0
|
|
||||||
pin_input_text_field: ^4.1.0
|
pin_input_text_field: ^4.1.0
|
||||||
flutter_icons_null_safety: ^1.1.0
|
flutter_icons_null_safety: ^1.1.0
|
||||||
country_icons: ^2.0.2
|
country_icons: ^2.0.2
|
||||||
@@ -59,6 +58,7 @@ dependencies:
|
|||||||
qr_flutter: ^4.1.0
|
qr_flutter: ^4.1.0
|
||||||
flutter_markdown: ^0.6.20+1
|
flutter_markdown: ^0.6.20+1
|
||||||
flutter_slidable: ^3.1.1
|
flutter_slidable: ^3.1.1
|
||||||
|
country_picker: ^2.0.26
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
|
|||||||
Reference in New Issue
Block a user