Login Flow Completed

development_mirza
mirza.shafique 3 years ago
parent 4eb6faf415
commit c1245da605

@ -53,5 +53,6 @@
"hr": "س",
"min": "د",
"years": "سنة",
"months": "أشهر"
"months": "أشهر",
"userOtherAccount": "مستخدم حساب آخر"
}

@ -53,5 +53,6 @@
"hr": "Hr",
"min": "Min",
"years": "Years",
"months": "Months"
"months": "Months",
"userOtherAccount": "User Another Account"
}

@ -25,6 +25,5 @@ enum ViewState {
enum LoginType {
FROM_LOGIN,
SILENT_LOGIN,
REGISTER_BIO,
REGISTER_NEW_BIO,
SILENT_WITH_OTP,
}

@ -56,17 +56,33 @@ class Utils {
return await Future.delayed(Duration(milliseconds: millis));
}
static void showLoading() {
WidgetsBinding.instance.addPostFrameCallback((_) {
_isLoadingVisible = true;
showDialog(
context: navigatorKey.currentContext!,
barrierColor: Colors.black.withOpacity(0.5),
builder: (BuildContext context) => LoadingDialog(),
).then((value) {
_isLoadingVisible = false;
static void showLoading({bool isNeedBinding = true}) {
if (isNeedBinding) {
WidgetsBinding.instance.addPostFrameCallback((_) {
showLoadingDialog();
});
});
} else {
showLoadingDialog();
}
}
static void showLoadingDialog() {
_isLoadingVisible = true;
showDialog(
context: navigatorKey.currentContext!,
barrierColor: Colors.black.withOpacity(0.5),
builder: (BuildContext context) => LoadingDialog(),
).then((value) {
_isLoadingVisible = false;
}).catchError((e) {
print("--------------catchError---------------");
print(e);
}).onError(
(error, stackTrace) {
print("--------------onError---------------");
print(error);
},
);
}
static void hideLoading() {
@ -253,8 +269,6 @@ class Utils {
return DateFormat('dd-MMM-yyyy').format(date);
}
static String reverseFormatDate(String date) {
String formattedDate;
if (date.isNotEmpty) {
@ -340,9 +354,6 @@ class Utils {
return selectedDate;
}
// static void readNFc({required Function(String) onRead}) {
//
// NfcManager.instance.startSession(onDiscovered: (NfcTag tag) async {

@ -19,7 +19,9 @@ class AppState {
int projectID = 0;
int clinicId = 0;
int lastLoginTyp = 0;
//TODO: Must be -1 before login or logout
int lastLoginTyp = -1;
int? doctorUserId;
String? password;
String? doctorIdFromDB;

@ -10,7 +10,6 @@ import 'package:hmg_nurses/config/routes.dart';
import 'package:hmg_nurses/provider/dashboard_provider_model.dart';
import 'package:hmg_nurses/provider/login_provider_model.dart';
import 'package:hmg_nurses/theme/app_theme.dart';
import 'package:hmg_nurses/ui/login/login_vm.dart';
import 'package:injector/injector.dart';
import 'package:logger/logger.dart';
import 'package:provider/provider.dart';
@ -21,7 +20,6 @@ import 'generated/codegen_loader.g.dart';
late AppState appState;
// GlobalKey<NavigatorState> navigatorKey = GlobalKey();
final navigatorKey = GlobalKey<NavigatorState>();
Logger logger = Logger(
@ -61,9 +59,6 @@ Future<void> main() async {
ChangeNotifierProvider<LoginProviderModel>(
create: (_) => LoginProviderModel(),
),
ChangeNotifierProvider<LoginViewModel>(
create: (_) => LoginViewModel(),
),
ChangeNotifierProvider<DashboardProviderModel>(
create: (_) => DashboardProviderModel(),
)
@ -89,32 +84,30 @@ class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return LayoutBuilder(
builder: (context, constraints) {
return Sizer(
builder: (
BuildContext context,
Orientation orientation,
DeviceType deviceType,
) {
SizeConfig().init(constraints, orientation);
List<LocalizationsDelegate<dynamic>> delegates = context.localizationDelegates;
return MaterialApp(
// key: navigatorKey,
navigatorKey: navigatorKey,
theme: AppTheme.getTheme(
EasyLocalization.of(context)?.locale.languageCode == "ar",
),
debugShowCheckedModeBanner: false,
localizationsDelegates: delegates,
supportedLocales: context.supportedLocales,
locale: context.locale,
initialRoute: AppRoutes.initialPage,
routes: AppRoutes.routes,
);
},
);
}
);
return LayoutBuilder(builder: (context, constraints) {
return Sizer(
builder: (
BuildContext context,
Orientation orientation,
DeviceType deviceType,
) {
SizeConfig().init(constraints, orientation);
List<LocalizationsDelegate<dynamic>> delegates = context.localizationDelegates;
return MaterialApp(
// key: navigatorKey,
navigatorKey: navigatorKey,
theme: AppTheme.getTheme(
EasyLocalization.of(context)?.locale.languageCode == "ar",
),
debugShowCheckedModeBanner: false,
localizationsDelegates: delegates,
supportedLocales: context.supportedLocales,
locale: context.locale,
initialRoute: AppRoutes.initialPage,
routes: AppRoutes.routes,
);
},
);
});
}
}

@ -1,5 +1,6 @@
import 'dart:convert';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
@ -7,6 +8,7 @@ import 'package:hmg_nurses/classes/consts.dart';
import 'package:hmg_nurses/classes/enums.dart';
import 'package:hmg_nurses/classes/utils.dart';
import 'package:hmg_nurses/config/routes.dart';
import 'package:hmg_nurses/generated/locale_keys.g.dart';
import 'package:hmg_nurses/main.dart';
import 'package:hmg_nurses/model/base/generic_response_model.dart';
import 'package:hmg_nurses/model/base/generic_response_model2.dart';
@ -69,13 +71,12 @@ class LoginProviderModel extends BaseViewModel {
Future<bool> loginWithFaceIDAndBiometrics() async {
IOSAuthMessages iosStrings =
const IOSAuthMessages(cancelButton: 'cancel', goToSettingsButton: 'settings', goToSettingsDescription: 'Please set up your Touch ID.', lockOut: 'Please reenable your Touch ID');
const IOSAuthMessages(cancelButton: 'cancel', goToSettingsButton: 'settings', goToSettingsDescription: 'Please set up your Touch ID.', lockOut: 'Please re-enable your Touch ID');
bool authenticated = false;
try {
authenticated = await auth.authenticate(localizedReason: 'Scan your fingerprint to authenticate', useErrorDialogs: true, stickyAuth: true, biometricOnly: true, iOSAuthStrings: iosStrings);
} on PlatformException catch (e) {
print(e);
Utils.hideLoading();
Utils.showToast("Please enable your Touch or Face ID");
}
return authenticated;
@ -96,6 +97,21 @@ class LoginProviderModel extends BaseViewModel {
}
}
String getType(type) {
switch (type) {
case 1:
return LocaleKeys.sms.tr();
case 3:
return LocaleKeys.fingerPrint.tr();
case 4:
return LocaleKeys.face.tr();
case 2:
return LocaleKeys.whatsapp.tr();
default:
return LocaleKeys.sms.tr();
}
}
// LoginType getDirectLoginType(type) {
// switch (type) {
// case 1:
@ -139,8 +155,9 @@ class LoginProviderModel extends BaseViewModel {
appState.setMemberBeforeLogin = memberLogin;
appState.projectID = branchId;
appState.logInTokenID = memberLogin.logInTokenId;
appState.lastLoginTyp=-1;
Utils.hideLoading();
Navigator.pushNamed(navigatorKey.currentContext!, AppRoutes.loginMethodsPage, arguments: LoginType.FROM_LOGIN);
Navigator.pushReplacementNamed(navigatorKey.currentContext!, AppRoutes.loginMethodsPage, arguments: LoginType.FROM_LOGIN);
return true;
} catch (e) {
Utils.hideLoading();
@ -151,24 +168,27 @@ class LoginProviderModel extends BaseViewModel {
}
}
Future<GenericResponseModel?> sendActivationCode(MemberLoginModel memberLoginModel, int facilityID, int sendOtpType, bool isFromSilentLogin) async {
Future<GenericResponseModel?> sendActivationCode(MemberLoginModel memberLoginModel, int facilityID, int sendOtpType, LoginType loginType, {bool isNeedBinding = true}) async {
try {
Utils.showLoading();
Utils.showLoading(isNeedBinding: isNeedBinding);
GenericResponseModel memberLogin;
if (isFromSilentLogin) {
memberLogin = await _loginApiRepo.sendActivationCodeForSlientLogin(memberLoginModel, facilityID, sendOtpType);
} else {
memberLogin = await _loginApiRepo.sendActivationCode(memberLoginModel, facilityID, sendOtpType);
}
appState.logInTokenID = memberLogin.logInTokenId.toString();
// Utils.showToast(deviceInfo.length.toString());
Utils.hideLoading();
// Navigator.pushNamed(navigatorKey.currentContext!, AppRoutes.loginMethodsPage, arguments: LoginType.FROM_LOGIN);
if(isFromSilentLogin){
checkActivationCode("0000", sendOtpType, isFromSilentLogin);
}else{
startSMSService(sendOtpType, isFromSilentLogin);
if (loginType == LoginType.FROM_LOGIN) {
memberLogin = await _loginApiRepo.sendActivationCode(memberLoginModel, facilityID, sendOtpType);
appState.logInTokenID = memberLogin.logInTokenId.toString();
Utils.hideLoading();
startSMSService(sendOtpType, false);
} else {
if (loginType == LoginType.SILENT_LOGIN) {
memberLogin = await _loginApiRepo.sendActivationCodeForSlientLogin(memberLoginModel, facilityID, sendOtpType);
appState.logInTokenID = memberLogin.logInTokenId.toString();
checkActivationCode("0000", sendOtpType, true);
} else {
memberLogin = await _loginApiRepo.sendActivationCodeForSlientLogin(memberLoginModel, facilityID, sendOtpType);
appState.logInTokenID = memberLogin.logInTokenId.toString();
Utils.hideLoading();
startSMSService(sendOtpType, true);
}
}
return memberLogin;
@ -178,15 +198,16 @@ class LoginProviderModel extends BaseViewModel {
Utils.confirmDialog(navigatorKey.currentContext!, msg);
});
}
return null;
}
Future<GenericResponseModel?> checkActivationCode(String activationCode, int sendOtpType, bool isFromSilentLogin) async {
try {
Utils.showLoading();
if (!isFromSilentLogin) Utils.showLoading();
GenericResponseModel memberLogin = await _loginApiRepo.checkActivationCode(activationCode, sendOtpType, isFromSilentLogin);
Utils.hideLoading();
setSession(memberLogin);
Navigator.pushNamed(navigatorKey.currentContext!, AppRoutes.dashboard);
Navigator.pushReplacementNamed(navigatorKey.currentContext!, AppRoutes.dashboard);
return memberLogin;
} catch (e) {
Utils.hideLoading();
@ -241,6 +262,7 @@ class LoginProviderModel extends BaseViewModel {
String lastLoginDate = await Utils.getStringFromPrefs(SharedPrefsConsts.lastLoginDate);
appState.setMemberBeforeLogin = await MemberLoginModel.getFromPrefs();
appState.lastLoginTyp = -1;
appState.doctorUserId = doctorUserId;
appState.password = password;
appState.logInTokenID = logInTokenID;
@ -251,7 +273,7 @@ class LoginProviderModel extends BaseViewModel {
appState.clinicId = clinicId;
appState.lastLoginImeiDate = model;
appState.lastLoginDate = lastLoginDate;
Navigator.pushNamed(navigatorKey.currentContext!, AppRoutes.loginMethodsPage, arguments: LoginType.SILENT_LOGIN);
Navigator.pushReplacementNamed(navigatorKey.currentContext!, AppRoutes.loginMethodsPage, arguments: LoginType.SILENT_LOGIN);
}
}
}

@ -116,7 +116,7 @@ class LoginApiRepo implements ILoginApiRepo {
postParams.addAll(appState.postParamsJson);
postParams["MobileNumber"] = memberLoginModel.mobileNumber;
postParams["ZipCode"] = memberLoginModel.zipCode;
postParams["IsMobileFingerPrint"] = sendOtpType;
postParams["IsMobileFingerPrint"] = 1;
postParams["IMEI"] = appState.imei;
postParams["LoginDoctorID"] = memberLoginModel.doctorId;
postParams["DoctorID"] = memberLoginModel.doctorId;

@ -1,5 +1,6 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:hmg_nurses/config/routes.dart';
import 'package:hmg_nurses/main.dart';
import 'package:hmg_nurses/provider/dashboard_provider_model.dart';
import 'package:provider/provider.dart';
@ -21,6 +22,20 @@ class _DashboardPageState extends State<DashboardPage> {
@override
Widget build(BuildContext context) {
return Scaffold();
return Scaffold(
appBar: AppBar(
actions: [
IconButton(
onPressed: () {
Navigator.pushReplacementNamed(context, AppRoutes.login, arguments: false);
},
icon: const Icon(
Icons.logout,
color: Colors.white,
),
)
],
),
);
}
}

@ -4,6 +4,7 @@ import 'package:hexcolor/hexcolor.dart';
import 'package:hmg_nurses/classes/colors.dart';
import 'package:hmg_nurses/classes/date-utils.dart';
import 'package:hmg_nurses/classes/enums.dart';
import 'package:hmg_nurses/config/routes.dart';
import 'package:hmg_nurses/extensions/int_extensions.dart';
import 'package:hmg_nurses/extensions/string_extensions.dart';
import 'package:hmg_nurses/extensions/util_extensions.dart';
@ -11,7 +12,6 @@ import 'package:hmg_nurses/extensions/widget_extensions.dart';
import 'package:hmg_nurses/generated/locale_keys.g.dart';
import 'package:hmg_nurses/main.dart';
import 'package:hmg_nurses/provider/login_provider_model.dart';
import 'package:hmg_nurses/ui/login/login_vm.dart';
import 'package:hmg_nurses/ui/login/widgets/verification_method_card.dart';
import 'package:hmg_nurses/widgets/button/default_button.dart';
import 'package:local_auth/local_auth.dart';
@ -33,7 +33,7 @@ class LoginMethodsPage extends StatefulWidget {
class LoginMethodsPageState extends State<LoginMethodsPage> {
bool isMoreOption = false;
bool onlySMSBox = false;
late LoginViewModel loginViewModel;
LoginType? loginType;
AuthMethodTypes? selectedAuthType;
late LoginProviderModel loginProviderModel;
@ -43,396 +43,241 @@ class LoginMethodsPageState extends State<LoginMethodsPage> {
if (loginType == null) {
loginType = ModalRoute.of(context)!.settings.arguments as LoginType;
}
loginViewModel = context.read<LoginViewModel>();
loginProviderModel = context.read<LoginProviderModel>();
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.transparent,
leading: IconButton(
icon: const Icon(Icons.arrow_back_ios, color: MyColors.darkIconColor),
onPressed: () => Navigator.pop(context),
),
// actions: [Center(child: "Employee Digital ID".toText12(color: MyColors.textMixColor, isUnderLine: true).onPress(() {})), 21.width],
),
// appBar: AppBar(
// backgroundColor: Colors.transparent,
// leading: null,
// // actions: [Center(child: "Employee Digital ID".toText12(color: MyColors.textMixColor, isUnderLine: true).onPress(() {})), 21.width],
// ),
body: Container(
width: double.infinity,
height: double.infinity,
padding: const EdgeInsets.all(21),
child: Column(
children: [
if (loginType == LoginType.SILENT_LOGIN && appState.lastLoginImeiDate != null)
Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
LocaleKeys.welcomeBack.tr().toText12(),
(appState.lastLoginImeiDate!.titleDescription! + " " + appState.lastLoginImeiDate!.doctorName!).toText20(isBold: true),
heightSpacer3per(),
LocaleKeys.wouldYouLikeToLoginWithCurrentUsername.tr().toText14(),
heightSpacer3per(),
Container(
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: const BorderRadius.all(Radius.circular(10)),
border: Border.all(color: HexColor('#707070'), width: 0.1),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Expanded(
child: SafeArea(
child: SingleChildScrollView(
child: Column(
children: [
21.height,
if (loginType == LoginType.SILENT_LOGIN && appState.lastLoginImeiDate != null)
Column(
mainAxisAlignment: MainAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
LocaleKeys.lastLoginDetails.tr().toText13(),
SizedBox(
width: 55.w,
children: <Widget>[
LocaleKeys.welcomeBack.tr().toText12(),
(appState.lastLoginImeiDate!.titleDescription! + " " + appState.lastLoginImeiDate!.doctorName!).toText20(isBold: true),
heightSpacer3per(),
LocaleKeys.wouldYouLikeToLoginWithCurrentUsername.tr().toText14(),
heightSpacer3per(),
Container(
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: const BorderRadius.all(Radius.circular(10)),
border: Border.all(color: HexColor('#707070'), width: 0.1),
),
child: Row(
children: [
"${LocaleKeys.verificationType.tr()} : ".toText11(),
loginViewModel.getType(appState.lastLoginImeiDate!.logInTypeID ?? 1).toText11(isBold: true),
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
LocaleKeys.lastLoginDetails.tr().toText13(),
SizedBox(
width: 55.w,
child: Row(
children: [
"${LocaleKeys.verificationType.tr()} : ".toText11(),
loginProviderModel.getType(appState.lastLoginImeiDate!.logInTypeID ?? 1).toText11(isBold: true),
],
),
),
],
),
Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.end,
children: [
(appState.lastLoginImeiDate!.editedOn != null
? AppDateUtils.getDayMonthYearDateFormatted(AppDateUtils.convertStringToDate(appState.lastLoginImeiDate!.editedOn ?? ""), isMonthShort: true)
: appState.lastLoginImeiDate!.createdOn != null
? AppDateUtils.getDayMonthYearDateFormatted(AppDateUtils.convertStringToDate(appState.lastLoginImeiDate!.createdOn ?? ""), isMonthShort: true)
: '--')
.toText11(isBold: true),
heightSpacer06per(),
(appState.lastLoginImeiDate!.editedOn != null
? AppDateUtils.getHour(AppDateUtils.convertStringToDate(appState.lastLoginImeiDate!.editedOn ?? ""))
: appState.lastLoginImeiDate!.createdOn != null
? AppDateUtils.getHour(AppDateUtils.convertStringToDate(appState.lastLoginImeiDate!.createdOn ?? ""))
: '--')
.toText10()
],
)
],
),
),
heightSpacer3per(),
LocaleKeys.pleaseVerify.tr().toText14().paddingOnly(left: 1.w),
heightSpacer2per(),
],
),
Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.end,
children: [
(appState.lastLoginImeiDate!.editedOn != null
? AppDateUtils.getDayMonthYearDateFormatted(AppDateUtils.convertStringToDate(appState.lastLoginImeiDate!.editedOn ?? ""), isMonthShort: true)
: appState.lastLoginImeiDate!.createdOn != null
? AppDateUtils.getDayMonthYearDateFormatted(AppDateUtils.convertStringToDate(appState.lastLoginImeiDate!.createdOn ?? ""), isMonthShort: true)
: '--')
.toText11(isBold: true),
heightSpacer06per(),
(appState.lastLoginImeiDate!.editedOn != null
? AppDateUtils.getHour(AppDateUtils.convertStringToDate(appState.lastLoginImeiDate!.editedOn ?? ""))
: appState.lastLoginImeiDate!.createdOn != null
? AppDateUtils.getHour(AppDateUtils.convertStringToDate(appState.lastLoginImeiDate!.createdOn ?? ""))
: '--')
.toText10()
],
)
],
),
),
heightSpacer3per(),
LocaleKeys.pleaseVerify.tr().toText14().paddingOnly(left: 1.w),
heightSpacer2per(),
],
),
Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
if (loginType == LoginType.FROM_LOGIN || loginType == LoginType.REGISTER_NEW_BIO)
Column(
children: [
LocaleKeys.pleaseVerifyForBio.tr().toText14(),
21.height,
],
),
if (loginType == LoginType.FROM_LOGIN || loginType == LoginType.SILENT_LOGIN)
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Expanded(
child: VerificationMethodsList(
authMethodType: AuthMethodTypes.faceID,
isBioAvailable: loginProviderModel.isFaceBioAvailable,
authenticateUser: (AuthMethodTypes authMethodType, isActive) async {
// loginViewModel.startSMSService(authMethodType, context: context);
// appState.setMemberBeforeLogin
bool isAuthenticated = await loginProviderModel.loginWithFaceIDAndBiometrics();
if (isAuthenticated) {
appState.lastLoginTyp = loginProviderModel.getLoginMethodId(AuthMethodTypes.faceID);
if (loginType == LoginType.FROM_LOGIN) {
setState(() {
loginType = LoginType.REGISTER_NEW_BIO;
selectedAuthType = AuthMethodTypes.faceID;
});
} else if (loginType == LoginType.SILENT_LOGIN) {
if (appState.lastLoginImeiDate!.logInTypeID == loginProviderModel.getLoginMethodId(AuthMethodTypes.faceID)) {
loginProviderModel.sendActivationCode(
appState.memberBeforeLogin!,
appState.projectID,
loginProviderModel.getLoginMethodId(AuthMethodTypes.sms),
true,
);
} else {
setState(() {
loginType = LoginType.REGISTER_NEW_BIO;
selectedAuthType = AuthMethodTypes.faceID;
});
}
}
} else {
print("Authentaction Failded");
}
},
),
),
21.width,
Expanded(
child: VerificationMethodsList(
authMethodType: AuthMethodTypes.fingerPrint,
isBioAvailable: loginProviderModel.isFingerBioAvailable,
onShowMore: () async {
bool isAuthenticated = await loginProviderModel.loginWithFaceIDAndBiometrics();
if (isAuthenticated) {
if (loginType == LoginType.FROM_LOGIN) {
appState.lastLoginTyp = loginProviderModel.getLoginMethodId(AuthMethodTypes.fingerPrint);
loginType = LoginType.REGISTER_NEW_BIO;
selectedAuthType = AuthMethodTypes.fingerPrint;
setState(() {});
}
} else {
print("Authentaction Failded");
}
},
),
),
],
),
21.height,
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Expanded(
child: VerificationMethodsList(
authMethodType: AuthMethodTypes.sms,
authenticateUser: (AuthMethodTypes authMethodType, isActive) {
// loginViewModel.startSMSService(authMethodType, context: context);
if (selectedAuthType == null) {
appState.lastLoginTyp = loginProviderModel.getLoginMethodId(AuthMethodTypes.sms);
} else if (selectedAuthType == AuthMethodTypes.faceID || selectedAuthType == AuthMethodTypes.fingerPrint) {
appState.lastLoginTyp = loginProviderModel.getLoginMethodId(selectedAuthType!);
}
loginProviderModel.sendActivationCode(
appState.memberBeforeLogin!,
appState.projectID,
loginProviderModel.getLoginMethodId(AuthMethodTypes.sms),
false,
);
},
),
),
21.width,
Expanded(
child: VerificationMethodsList(
authMethodType: AuthMethodTypes.whatsApp,
authenticateUser: (AuthMethodTypes authMethodType, isActive) {
// loginViewModel.startSMSService(authMethodType, context: context);
if (selectedAuthType == null) {
appState.lastLoginTyp = loginProviderModel.getLoginMethodId(AuthMethodTypes.whatsApp);
} else if (selectedAuthType == AuthMethodTypes.faceID || selectedAuthType == AuthMethodTypes.fingerPrint) {
appState.lastLoginTyp = loginProviderModel.getLoginMethodId(selectedAuthType!);
}
loginProviderModel.sendActivationCode(
appState.memberBeforeLogin!,
appState.projectID,
loginProviderModel.getLoginMethodId(AuthMethodTypes.whatsApp),
false,
);
},
),
),
],
),
],
),
],
),
),
);
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.transparent,
leading: IconButton(
icon: const Icon(Icons.arrow_back_ios, color: MyColors.darkIconColor),
onPressed: () => Navigator.pop(context),
),
// actions: [Center(child: "Employee Digital ID".toText12(color: MyColors.textMixColor, isUnderLine: true).onPress(() {})), 21.width],
),
body: SingleChildScrollView(
child: Center(
child: FractionallySizedBox(
widthFactor: 0.9,
child: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
heightSpacer1per(),
if (loginViewModel.isFromLogin)
InkWell(
onTap: () {
// loginViewModel.setUnverified(false, isFromLogin: false);
// loginViewModel.setAppStatus(APPSTATUS.unAuthenticated);
},
child: const Icon(
Icons.arrow_back_ios,
color: MyColors.darkTextColor,
),
),
Column(
children: <Widget>[
heightSpacer1per(),
isMoreOption == false
? Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
LocaleKeys.welcomeBack.tr().toText12(),
"Dr Amal Ahmed".toText20(isBold: true),
heightSpacer3per(),
LocaleKeys.wouldYouLikeToLoginWithCurrentUsername.tr().toText14(),
heightSpacer3per(),
Container(
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: const BorderRadius.all(Radius.circular(10)),
border: Border.all(color: HexColor('#707070'), width: 0.1),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
LocaleKeys.lastLoginDetails.tr().toText13(),
SizedBox(
width: 55.w,
child: Row(
children: [
"${LocaleKeys.verificationType.tr()} : ".toText11(),
"${loginViewModel.getType(1)}".toText11(isBold: true),
],
),
),
],
),
Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.end,
children: ["12 NOV, 2022".toText11(isBold: true), heightSpacer06per(), "09:56 AM".toText10()],
)
],
),
),
heightSpacer3per(),
LocaleKeys.pleaseVerify.tr().toText14().paddingOnly(left: 1.w),
heightSpacer2per(),
],
)
: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
LocaleKeys.pleaseVerifyForBio.tr().toText14().paddingAll(10),
Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
if (loginType == LoginType.FROM_LOGIN || loginType == LoginType.SILENT_WITH_OTP)
Column(
children: [
LocaleKeys.pleaseVerifyForBio.tr().toText14(),
21.height,
],
),
isMoreOption == false
? Column(mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: <Widget>[
Row(mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[
if (loginType == LoginType.FROM_LOGIN || loginType == LoginType.SILENT_LOGIN)
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Expanded(
child: VerificationMethodsList(
authMethodType: SelectedAuthMethodTypesService.getMethodsTypeService(1),
authenticateUser: (AuthMethodTypes authMethodType, isActive) {
loginViewModel.startSMSService(authMethodType, context: context);
authMethodType: AuthMethodTypes.faceID,
isBioAvailable: loginProviderModel.isFaceBioAvailable,
authenticateUser: (AuthMethodTypes authMethodType, isActive) async {
bool isAuthenticated = await loginProviderModel.loginWithFaceIDAndBiometrics();
if (isAuthenticated) {
appState.lastLoginTyp = loginProviderModel.getLoginMethodId(authMethodType);
if (loginType == LoginType.FROM_LOGIN) {
setState(() {
loginType = LoginType.FROM_LOGIN;
});
} else if (loginType == LoginType.SILENT_LOGIN) {
if (appState.lastLoginImeiDate!.logInTypeID == loginProviderModel.getLoginMethodId(authMethodType)) {
loginProviderModel.sendActivationCode(
appState.memberBeforeLogin!,
appState.projectID,
loginProviderModel.getLoginMethodId(AuthMethodTypes.sms),
loginType ?? LoginType.FROM_LOGIN,
isNeedBinding: false,
);
} else {
setState(() {
loginType = LoginType.SILENT_WITH_OTP;
});
}
}
} else {
print("Authentication Failed");
}
},
),
),
21.width,
Expanded(
child: VerificationMethodsList(
authMethodType: AuthMethodTypes.moreOptions,
onShowMore: () {
setState(() {
isMoreOption = true;
});
},
))
]),
])
: Column(mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: <Widget>[
onlySMSBox == false
? Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Expanded(
child: VerificationMethodsList(
authMethodType: AuthMethodTypes.fingerPrint,
authenticateUser: (AuthMethodTypes authMethodType, isActive) {
loginViewModel.startSMSService(authMethodType, context: context);
},
)),
Expanded(
child: VerificationMethodsList(
authMethodType: AuthMethodTypes.faceID,
authenticateUser: (AuthMethodTypes authMethodType, isActive) {
loginViewModel.startSMSService(authMethodType, context: context);
},
))
],
)
: const SizedBox(),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Expanded(
child: VerificationMethodsList(
authMethodType: AuthMethodTypes.sms,
authenticateUser: (AuthMethodTypes authMethodType, isActive) {
loginViewModel.startSMSService(authMethodType, context: context);
},
)),
Expanded(
child: VerificationMethodsList(
authMethodType: AuthMethodTypes.whatsApp,
authenticateUser: (AuthMethodTypes authMethodType, isActive) {
loginViewModel.startSMSService(authMethodType, context: context);
child: VerificationMethodsList(
authMethodType: AuthMethodTypes.fingerPrint,
isBioAvailable: loginProviderModel.isFingerBioAvailable,
authenticateUser: (AuthMethodTypes authMethodType, isActive) async {
bool isAuthenticated = await loginProviderModel.loginWithFaceIDAndBiometrics();
if (isAuthenticated) {
appState.lastLoginTyp = loginProviderModel.getLoginMethodId(authMethodType);
if (loginType == LoginType.FROM_LOGIN) {
setState(() {
loginType = LoginType.FROM_LOGIN;
});
} else if (loginType == LoginType.SILENT_LOGIN) {
if (appState.lastLoginImeiDate!.logInTypeID == loginProviderModel.getLoginMethodId(authMethodType)) {
loginProviderModel.sendActivationCode(
appState.memberBeforeLogin!,
appState.projectID,
loginProviderModel.getLoginMethodId(AuthMethodTypes.sms),
loginType ?? LoginType.FROM_LOGIN,
isNeedBinding: false,
);
} else {
setState(() {
loginType = LoginType.SILENT_WITH_OTP;
});
}
}
} else {
print("Authentication Failed");
}
},
))
],
),
),
],
),
21.height,
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Expanded(
child: VerificationMethodsList(
authMethodType: AuthMethodTypes.sms,
authenticateUser: (AuthMethodTypes authMethodType, isActive) {
if (loginType == LoginType.FROM_LOGIN || loginType == LoginType.SILENT_LOGIN) {
if (appState.lastLoginTyp == -1) appState.lastLoginTyp = loginProviderModel.getLoginMethodId(authMethodType);
if (loginType == LoginType.SILENT_LOGIN) {
loginType = LoginType.SILENT_WITH_OTP;
}
}
loginProviderModel.sendActivationCode(
appState.memberBeforeLogin!,
appState.projectID,
loginProviderModel.getLoginMethodId(AuthMethodTypes.sms),
loginType ?? LoginType.FROM_LOGIN,
);
},
),
),
]),
// )
],
),
],
),
),
),
),
),
bottomSheet: !isMoreOption
? null
: Container(
height: 10.h,
color: MyColors.backgroundColor,
width: double.infinity,
child: Center(
child: FractionallySizedBox(
widthFactor: 0.9,
child: Column(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
Padding(
padding: EdgeInsets.symmetric(horizontal: 4.w),
child: DefaultButton(LocaleKeys.useAnotherAccount.tr(), () {}, colors: const [MyColors.redColor, MyColors.redColor]),
21.width,
Expanded(
child: VerificationMethodsList(
authMethodType: AuthMethodTypes.whatsApp,
authenticateUser: (AuthMethodTypes authMethodType, isActive) {
if (loginType == LoginType.FROM_LOGIN || loginType == LoginType.SILENT_LOGIN) {
if (appState.lastLoginTyp == -1) appState.lastLoginTyp = loginProviderModel.getLoginMethodId(authMethodType);
if (loginType == LoginType.SILENT_LOGIN) {
loginType = LoginType.SILENT_WITH_OTP;
}
}
loginProviderModel.sendActivationCode(
appState.memberBeforeLogin!,
appState.projectID,
loginProviderModel.getLoginMethodId(AuthMethodTypes.whatsApp),
loginType ?? LoginType.FROM_LOGIN,
);
},
),
),
],
),
],
),
heightSpacer3per(),
12.height,
],
),
),
),
),
21.height,
DefaultButton(
LocaleKeys.useAnotherAccount.tr(),
() async {
Navigator.pushReplacementNamed(context, AppRoutes.login, arguments:false);
},
colors: const [
MyColors.redColor,
MyColors.redColor,
],
),
],
),
),
);
}
}

@ -23,11 +23,7 @@ import 'package:local_auth/local_auth.dart';
import 'package:provider/provider.dart';
import 'package:sizer/sizer.dart';
import '../../services/api_repo/login_api_repo.dart';
class LoginPage extends StatefulWidget {
const LoginPage({Key? key}) : super(key: key);
@override
State<LoginPage> createState() => _LoginPageState();
}
@ -35,25 +31,36 @@ class LoginPage extends StatefulWidget {
class _LoginPageState extends State<LoginPage> {
int branchID = 0;
late LoginProviderModel provider;
LoginProviderModel? provider;
final loginFormKey = GlobalKey<FormState>();
var projectIdController = TextEditingController();
var userIdController = TextEditingController();
var passwordController = TextEditingController();
@override
void initState() {
super.initState();
provider = Provider.of<LoginProviderModel>(navigatorKey.currentContext!);
checkUserSession();
checkUserSession() async {
provider!.checkLastSession();
}
checkUserSession() async {
provider.checkLastSession();
setUserSession() async {
await Utils.getStringFromPrefs(SharedPrefsConsts.username);
await Utils.getStringFromPrefs(SharedPrefsConsts.password);
}
@override
Widget build(BuildContext context) {
if (provider == null) {
dynamic? isNeedCheckUserSession = (ModalRoute.of(context)!.settings.arguments);
// setUserSession();
provider = context.read<LoginProviderModel>();
if (isNeedCheckUserSession == null) {
checkUserSession();
}
}
return Scaffold(
body: SafeArea(
child: Column(
@ -96,7 +103,7 @@ class _LoginPageState extends State<LoginPage> {
isTextIsPassword: true,
onChange: (v) {
if (v.length == 1) {
provider.getAssignedBranches(userIdController.text);
provider!.getAssignedBranches(userIdController.text);
}
},
),
@ -120,11 +127,11 @@ class _LoginPageState extends State<LoginPage> {
isEnable: false,
onClick: () => CustomCupertinoPicker.showCupertinoPicker(
context,
provider.assignedBranches,
provider!.assignedBranches,
(index) {
projectIdController.text = provider.assignedBranches[index].facilityName!;
branchID = provider.assignedBranches[index].facilityId as int;
provider.notifyListeners();
projectIdController.text = provider!.assignedBranches[index].facilityName!;
branchID = provider!.assignedBranches[index].facilityId as int;
provider!.notifyListeners();
},
),
);
@ -144,7 +151,7 @@ class _LoginPageState extends State<LoginPage> {
LocaleKeys.login.tr(),
() async {
// provider.checkLastSession();
bool isSuccess = await provider.performLogin(userIdController.text, passwordController.text, branchID);
bool isSuccess = await provider!.performLogin(userIdController.text, passwordController.text, branchID);
if (isSuccess) {
appState.password = passwordController.text;
appState.doctorUserId = int.parse(userIdController.text);

@ -1,134 +0,0 @@
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:hmg_nurses/provider/base_vm.dart';
import 'package:hmg_nurses/classes/enums.dart';
import 'package:hmg_nurses/classes/utils.dart';
import 'package:hmg_nurses/generated/locale_keys.g.dart';
import 'package:hmg_nurses/widgets/dialogs/otp_dialog.dart';
import 'package:local_auth/local_auth.dart';
class LoginViewModel extends BaseViewModel {
bool isLogin = false;
bool unverified = false;
bool isFromLogin = false;
String localToken = "";
String nurseProfile = "";
final LocalAuthentication auth = LocalAuthentication();
late List<BiometricType> _availableBiometrics;
LoginViewModel();
/// get type name based on id.
String getType(type) {
switch (type) {
case 1:
return LocaleKeys.sms.tr();
case 3:
return LocaleKeys.fingerPrint.tr();
case 4:
return LocaleKeys.face.tr();
case 2:
return LocaleKeys.whatsapp.tr();
default:
return LocaleKeys.sms.tr();
}
}
int getLoginMethodId(AuthMethodTypes authMethodTypes) {
switch (authMethodTypes) {
case AuthMethodTypes.sms:
return 1;
case AuthMethodTypes.whatsApp:
return 2;
case AuthMethodTypes.fingerPrint:
return 3;
case AuthMethodTypes.faceID:
return 4;
default:
return 1;
}
}
/// ask user to add his biometric
showIOSAuthMessages() async {
try {
await auth.authenticate(
localizedReason: 'Scan your fingerprint to authenticate',
);
} on PlatformException catch (e) {
if (kDebugMode) {
print(e);
}
}
}
/// check specific biometric if it available or not
Future<bool> checkIfBiometricAvailable(BiometricType biometricType) async {
bool isAvailable = false;
await _getAvailableBiometrics();
if (_availableBiometrics != null) {
for (var i = 0; i < _availableBiometrics.length; i++) {
if (biometricType == _availableBiometrics[i]) isAvailable = true;
}
}
return isAvailable;
}
/// get all available biometric on the device for local Auth service
Future<void> _getAvailableBiometrics() async {
try {
_availableBiometrics = await auth.getAvailableBiometrics();
} on PlatformException catch (e) {
if (kDebugMode) {
print(e);
}
}
}
/// determine the status of the ap
setUnverified(bool unverified, {bool isFromLogin = false}) {
this.unverified = unverified;
this.isFromLogin = isFromLogin;
notifyListeners();
}
/// logout function
logout({bool isFromLogin = false}) async {
// localToken = "";
// String lang = await sharedPref.getString(APP_Language);
// await Utils.clearSharedPref();
// doctorProfile = null;
// sharedPref.setString(APP_Language, lang);
// deleteUser();
// await getDeviceInfoFromFirebase();
// this.isFromLogin = isFromLogin;
// appStatus = APPSTATUS.unAuthenticated;
// setState(ViewState.Idle);
}
deleteUser() {
// user = null;
// unverified = false;
// isLogin = false;
}
startSMSService(AuthMethodTypes type, {isSilentLogin = false, required BuildContext context}) {
OtpDialog(
type: 1,
mobileNo: "0504278212",
onSuccess: (String otpCode, TextEditingController pinPut) {
Utils.showLoading();
//TODO: API CALL
// performDirectApiCall(_title, _icon, _flag, value);
},
onFailure: () => Navigator.pop(context),
onResendCode: () {},
).displayDialog(context);
}
}

@ -6,7 +6,7 @@ import 'package:hmg_nurses/classes/colors.dart';
import 'package:hmg_nurses/classes/enums.dart';
import 'package:hmg_nurses/classes/size_config.dart';
import 'package:hmg_nurses/generated/locale_keys.g.dart';
import 'package:hmg_nurses/ui/login/login_vm.dart';
import 'package:local_auth/local_auth.dart';
class VerificationMethodsList extends StatelessWidget {

@ -216,9 +216,11 @@ class OtpDialog {
void startTimer(setState) {
remainingTime--;
if (stopTimer) return;
setState(() {
displayTime = getSecondsAsDigitalClock(remainingTime);
});
try {
setState(() {
displayTime = getSecondsAsDigitalClock(remainingTime);
});
} catch (e) {}
timer = Future.delayed(const Duration(seconds: 1), () {
if (remainingTime > 0) {

Loading…
Cancel
Save