login flow complete

pull/24/head
Sultan khan 2 months ago
parent 58d33e2dae
commit 299c0b0e29

@ -726,7 +726,7 @@ const DEACTIVATE_ACCOUNT = 'Services/Patients.svc/REST/PatientAppleActivation_In
class ApiConsts {
static const maxSmallScreen = 660;
static AppEnvironmentTypeEnum appEnvironmentType = AppEnvironmentTypeEnum.uat;
static AppEnvironmentTypeEnum appEnvironmentType = AppEnvironmentTypeEnum.prod;
// static String baseUrl = 'https://uat.hmgwebservices.com/'; // HIS API URL UAT
@ -802,8 +802,8 @@ class ApiConsts {
static final String insertPatientDeviceIMEIData = 'Services/Patients.svc/REST/Patient_INSERTDeviceIMEI';
static final String insertPatientMobileData = 'Services/MobileNotifications.svc/REST/Insert_PatientMobileDeviceInfo';
static final String getPrivileges = 'Services/Patients.svc/REST/Service_Privilege';
static final String getPatientMobileData = '/Services/Authentication.svc/REST/GetMobileLoginInfo';
static final String getPrivileges = 'Services/Patients.svc/REST/Service_Privilege';
// static values for Api
static final double appVersionID = 18.7;

@ -35,6 +35,8 @@ abstract class AuthenticationRepo {
Future<Either<Failure, GenericApiModel<dynamic>>> insertPatientIMEIData({required dynamic patientIMEIDataRequest});
Future<Either<Failure, GenericApiModel<dynamic>>> insertPatientDeviceData({required dynamic patientDeviceDataRequest});
Future<Either<Failure, GenericApiModel<dynamic>>> getPatientDeviceData({required dynamic patientDeviceDataRequest});
}
class AuthenticationRepoImp implements AuthenticationRepo {
@ -456,4 +458,39 @@ class AuthenticationRepoImp implements AuthenticationRepo {
return Future.value(Left(UnknownFailure(e.toString())));
}
}
@override
Future<Either<Failure, GenericApiModel>> getPatientDeviceData({required patientDeviceDataRequest}) {
try {
GenericApiModel<dynamic>? apiResponse;
Failure? failure;
return apiClient.post(
ApiConsts.getPatientMobileData,
body: patientDeviceDataRequest,
onFailure: (error, statusCode, {messageStatus, failureType}) {
failure = failureType;
},
onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
try {
apiResponse = GenericApiModel<dynamic>(
messageStatus: messageStatus,
statusCode: statusCode,
errorMessage: errorMessage,
data: response,
);
} catch (e) {
failure = DataParsingFailure(e.toString());
}
},
).then( (_) {
if (failure != null) return Left(failure!);
if (apiResponse == null) return Left(ServerFailure("Unknown error"));
return Right(apiResponse!);
});
} catch (e) {
return Future.value(Left(UnknownFailure(e.toString())));
}
}
}

@ -30,7 +30,9 @@ import 'package:hmg_patient_app_new/services/dialog_service.dart';
import 'package:hmg_patient_app_new/services/error_handler_service.dart';
import 'package:hmg_patient_app_new/services/localauth_service.dart';
import 'package:hmg_patient_app_new/services/navigation_service.dart';
import 'package:hmg_patient_app_new/widgets/loader/bottomsheet_loader.dart';
import 'models/request_models/get_user_mobile_device_data.dart';
import 'models/request_models/insert_patient_mobile_deviceinfo.dart';
import 'models/request_models/patient_insert_device_imei_request.dart';
@ -78,10 +80,11 @@ class AuthenticationViewModel extends ChangeNotifier {
String errorMsg = '';
final FocusNode myFocusNode = FocusNode();
var healthId;
int getDeviceLastLogin =1;
Future<void> onLoginPressed() async {
try {
LoadingUtils.showFullScreenLoader();
LoaderBottomSheet.showLoader();
//TODO: We will remove this delay
// await Future.delayed(Duration(seconds: 3));
var data = _appState.getSelectDeviceByImeiRespModelElement;
@ -93,7 +96,7 @@ class AuthenticationViewModel extends ChangeNotifier {
}
} catch (e) {
log("Error in onLoginPressed: $e");
LoadingUtils.hideFullScreenLoader();
LoaderBottomSheet.hideLoader();
_dialogService.showErrorBottomSheet(message: "An unexpected error occurred. Please try again.", onOkPressed: () {});
}
}
@ -207,7 +210,7 @@ class AuthenticationViewModel extends ChangeNotifier {
Future<void> _handleExistingImeiData(dynamic data) async {
try {
SelectDeviceByImeiRespModelElement? savedData = _appState.getSelectDeviceByImeiRespModelElement;
LoadingUtils.hideFullScreenLoader();
LoaderBottomSheet.hideLoader();
if (savedData != null) {
// TODO: Navigate to SavedLogin when available
@ -216,7 +219,7 @@ class AuthenticationViewModel extends ChangeNotifier {
}
} catch (e) {
log("Error handling existing IMEI data: $e");
LoadingUtils.hideFullScreenLoader();
LoaderBottomSheet.hideLoader();
_navigationService.pushPage(page: LoginScreen());
}
}
@ -227,7 +230,7 @@ class AuthenticationViewModel extends ChangeNotifier {
if (respData != null) {
dynamic data = SelectDeviceByImeiRespModelElement.fromJson(respData.toJson());
_appState.setSelectDeviceByImeiRespModelElement(data);
LoadingUtils.hideFullScreenLoader();
LoaderBottomSheet.hideLoader();
// TODO: Navigate to SavedLogin when available
// SelectDeviceByImeiRespModelElement savedData =
@ -235,16 +238,16 @@ class AuthenticationViewModel extends ChangeNotifier {
_navigationService.pushPage(page: SavedLogin());
// _navigationService.pushPage(page: LoginScreen());
} else {
LoadingUtils.hideFullScreenLoader();
LoaderBottomSheet.hideLoader();
_navigationService.pushPage(page: LoginScreen());
}
} catch (e) {
log("Error processing IMEI registration response: $e");
LoadingUtils.hideFullScreenLoader();
LoaderBottomSheet.hideLoader();
_navigationService.pushPage(page: LoginScreen());
}
}, onError: (String error) {
LoadingUtils.hideFullScreenLoader();
LoaderBottomSheet.hideLoader();
_dialogService.showErrorBottomSheet(message: error, onOkPressed: () {});
});
}
@ -265,8 +268,8 @@ class AuthenticationViewModel extends ChangeNotifier {
if (!isValidated) {
return;
}
LoadingUtils.showFullScreenLoader();
LoaderBottomSheet.showLoader();
// LoadingUtils.showFullScreenLoader();
dynamic checkPatientAuthenticationReq = RequestUtils.getPatientAuthenticationRequest(
phoneNumber: phoneNumberController.text,
@ -279,20 +282,22 @@ class AuthenticationViewModel extends ChangeNotifier {
calenderType: calenderType);
final result = await _authenticationRepo.checkPatientAuthentication(checkPatientAuthenticationReq: checkPatientAuthenticationReq);
LoadingUtils.hideFullScreenLoader();
result.fold(
(failure) async => await _errorHandlerService.handleError(failure: failure),
(apiResponse) async {
if (apiResponse.messageStatus == 2) {
LoaderBottomSheet.hideLoader();
await _dialogService.showErrorBottomSheet(message: apiResponse.errorMessage ?? "ErrorEmpty", onOkPressed: () {});
} else if (apiResponse.messageStatus == 1) {
if (apiResponse.data['isSMSSent']) {
_appState.setAppAuthToken = apiResponse.data['LogInTokenID'];
sendActivationCode(
await sendActivationCode(
otpTypeEnum: otpTypeEnum,
phoneNumber: phoneNumberController.text,
nationalIdOrFileNumber: nationalIdController.text,
);
} else {
if (apiResponse.data['IsAuthenticated']) {
await checkActivationCode(
@ -300,6 +305,7 @@ class AuthenticationViewModel extends ChangeNotifier {
onWrongActivationCode: (String? message) {},
activationCode: null, //todo silent login case halded on the repo itself..
);
}
}
}
@ -347,9 +353,11 @@ class AuthenticationViewModel extends ChangeNotifier {
(failure) async => await _errorHandlerService.handleError(failure: failure),
(apiResponse) async {
if (apiResponse.messageStatus == 2) {
LoaderBottomSheet.hideLoader();
await _dialogService.showErrorBottomSheet(message: apiResponse.errorMessage ?? "ErrorEmpty");
} else {
if (apiResponse.data != null && apiResponse.data['isSMSSent'] == true) {
LoaderBottomSheet.hideLoader();
navigateToOTPScreen(otpTypeEnum: otpTypeEnum, phoneNumber: phoneNumber);
} else {
// TODO: Handle isSMSSent false
@ -384,7 +392,7 @@ class AuthenticationViewModel extends ChangeNotifier {
countryCode: selectedCountrySignup.countryCode,
loginType: loginTypeEnum.toInt)
.toJson();
LoaderBottomSheet.showLoader();
bool isForRegister = (_appState.getUserRegistrationPayload.healthId != null || _appState.getUserRegistrationPayload.patientOutSa == true);
if (isForRegister) {
if (_appState.getUserRegistrationPayload.patientOutSa == true) request['DOB'] = _appState.getUserRegistrationPayload.dob;
@ -393,6 +401,8 @@ class AuthenticationViewModel extends ChangeNotifier {
final resultEither = await _authenticationRepo.checkActivationCodeRepo(newRequest: request, activationCode: activationCode.toString(), isRegister: true);
LoaderBottomSheet.hideLoader();
resultEither.fold((failure) async => await _errorHandlerService.handleError(failure: failure), (apiResponse) {
final activation = CheckActivationCode.fromJson(apiResponse.data as Map<String, dynamic>);
if (_appState.getUserRegistrationPayload.isRegister == true) {
@ -412,19 +422,26 @@ class AuthenticationViewModel extends ChangeNotifier {
resultEither.fold((failure) async => await _errorHandlerService.handleError(failure: failure), (apiResponse) async {
final activation = CheckActivationCode.fromJson(apiResponse.data as Map<String, dynamic>);
if (activation.errorCode == '699') {
// Todo: Hide Loader
// GifLoaderDialogUtils.hideDialog(context);
LoaderBottomSheet.hideLoader();
onWrongActivationCode(activation.errorEndUserMessage);
return;
} else if (activation.messageStatus == 2) {
LoaderBottomSheet.hideLoader();
onWrongActivationCode(activation.errorEndUserMessage);
return;
} else if (_appState.getUserRegistrationPayload.isRegister == true) {
LoaderBottomSheet.hideLoader();
_navigationService.pushAndReplace(AppRoutes.registerStepTwo);
// Navigator.popUntil(context, (route) => Utils.route(route, equalsTo: RegisterNew));
return;
} else {
if (activation.list != null && activation.list!.isNotEmpty) {
_appState.setAuthenticatedUser(activation.list!.first);
}
@ -432,6 +449,11 @@ class AuthenticationViewModel extends ChangeNotifier {
_appState.setAppAuthToken = activation.authenticationTokenId;
final request = RequestUtils.getAuthanticatedCommonRequest().toJson();
bool isUserAgreedBefore = await checkIfUserAgreedBefore(request: request);
//updating the last login type in app state to show the fingerprint/face id option on home screen
_appState.getSelectDeviceByImeiRespModelElement!.logInType = loginTypeEnum.toInt;
LoaderBottomSheet.hideLoader();
insertPatientIMEIData(loginTypeEnum.toInt);
clearDefaultInputValues();
if (isUserAgreedBefore) {
@ -521,18 +543,19 @@ class AuthenticationViewModel extends ChangeNotifier {
loginWithFingerPrintFace(Function success) async {
_localAuthService.authenticate().then((value) async {
if (value) {
// we have to handle this if verification true;
LoaderBottomSheet.showLoader();
success();
loginTypeEnum = (_appState.deviceTypeID == 1 ? LoginTypeEnum.face : LoginTypeEnum.fingerprint);
if (!_appState.isAuthenticated) {
loginTypeEnum = (_appState.deviceTypeID == 1 ? LoginTypeEnum.face : LoginTypeEnum.fingerprint);
print(loginTypeEnum);
checkActivationCode(otpTypeEnum: OTPTypeEnum.faceIDFingerprint, activationCode: null, onWrongActivationCode: (String? message) {});
insertPatientIMEIData((_appState.deviceTypeID == 1 ? LoginTypeEnum.face.toInt : LoginTypeEnum.fingerprint.toInt));
//commenting this api to check either the same flow working or not because this api does not needed further if work fine we will remove this
// await getPatientDeviceData(loginTypeEnum.toInt);
await checkActivationCode(otpTypeEnum: OTPTypeEnum.faceIDFingerprint, activationCode: null, onWrongActivationCode: (String? message) {});
await insertPatientIMEIData(loginTypeEnum.toInt);
} else {
// authenticated = true;
insertPatientIMEIData((_appState.deviceTypeID == 1 ? LoginTypeEnum.face.toInt : LoginTypeEnum.fingerprint.toInt));
await insertPatientIMEIData(loginTypeEnum.toInt);
}
LoaderBottomSheet.hideLoader();
notifyListeners();
// navigateToHomeScreen();
} else {
@ -764,6 +787,32 @@ class AuthenticationViewModel extends ChangeNotifier {
}
Future<void> getPatientDeviceData(int loginType) async {
final resultEither = await _authenticationRepo.getPatientDeviceData(
patientDeviceDataRequest: GetUserMobileDeviceData(
deviceToken: _appState.deviceToken,
deviceTypeId: _appState.getDeviceTypeID(),
patientId: _appState.getSelectDeviceByImeiRespModelElement!.patientId!,
patientType: _appState.getSelectDeviceByImeiRespModelElement!.patientType,
patientOutSa:_appState.getSelectDeviceByImeiRespModelElement!.outSa == true ?1 :0,
loginType: loginType,
languageId: _appState.getLanguageID(),
latitude: _appState.userLat,
longitude: _appState.userLong,
mobileNo:_appState.getSelectDeviceByImeiRespModelElement!.mobile! ,
patientMobileNumber:int.parse(_appState.getSelectDeviceByImeiRespModelElement!.mobile!),
nationalId:_appState.getSelectDeviceByImeiRespModelElement!.identificationNo)
.toJson());
resultEither.fold((failure) async => await _errorHandlerService.handleError(failure: failure), (apiResponse) async {
if (apiResponse.messageStatus == 1) {
dynamic deviceInfo= apiResponse.data['List_MobileLoginInfo'];
getDeviceLastLogin = deviceInfo['LoginType'];
}
});
}
@override
void dispose() {
nationalIdController.dispose();

@ -0,0 +1,113 @@
import 'dart:convert';
class GetUserMobileDeviceData {
int? patientMobileNumber;
String? mobileNo;
String? deviceToken;
bool? projectOutSa;
int? loginType;
String? zipCode;
bool? isRegister;
String? logInTokenId;
int? searchType;
int? patientId;
String? nationalId;
String? patientIdentificationId;
int? otpSendType;
int? languageId;
double? versionId;
int? channel;
String? ipAdress;
String? generalid;
int? patientOutSa;
bool? isDentalAllowedBackend;
int? deviceTypeId;
double? latitude;
double? longitude;
int? patientType;
GetUserMobileDeviceData({
this.patientMobileNumber,
this.mobileNo,
this.deviceToken,
this.projectOutSa,
this.loginType,
this.zipCode,
this.isRegister,
this.logInTokenId,
this.searchType,
this.patientId,
this.nationalId,
this.patientIdentificationId,
this.otpSendType,
this.languageId,
this.versionId,
this.channel,
this.ipAdress,
this.generalid,
this.patientOutSa,
this.isDentalAllowedBackend,
this.deviceTypeId,
this.latitude,
this.longitude,
this.patientType,
});
factory GetUserMobileDeviceData.fromRawJson(String str) => GetUserMobileDeviceData.fromJson(json.decode(str));
String toRawJson() => json.encode(toJson());
factory GetUserMobileDeviceData.fromJson(Map<String, dynamic> json) => GetUserMobileDeviceData(
patientMobileNumber: json["PatientMobileNumber"],
mobileNo: json["MobileNo"],
deviceToken: json["DeviceToken"],
projectOutSa: json["ProjectOutSA"],
loginType: json["LoginType"],
zipCode: json["ZipCode"],
isRegister: json["isRegister"],
logInTokenId: json["LogInTokenID"],
searchType: json["SearchType"],
patientId: json["PatientID"],
nationalId: json["NationalID"],
patientIdentificationId: json["PatientIdentificationID"],
otpSendType: json["OTP_SendType"],
languageId: json["LanguageID"],
versionId: json["VersionID"]?.toDouble(),
channel: json["Channel"],
ipAdress: json["IPAdress"],
generalid: json["generalid"],
patientOutSa: json["PatientOutSA"],
isDentalAllowedBackend: json["isDentalAllowedBackend"],
deviceTypeId: json["DeviceTypeID"],
latitude: json["Latitude"],
longitude: json["Longitude"],
patientType: json["PatientType"],
);
Map<String, dynamic> toJson() => {
"PatientMobileNumber": patientMobileNumber,
"MobileNo": mobileNo,
"DeviceToken": deviceToken,
"ProjectOutSA": projectOutSa,
"LoginType": loginType,
"ZipCode": zipCode,
"isRegister": isRegister,
"LogInTokenID": logInTokenId,
"SearchType": searchType,
"PatientID": patientId,
"NationalID": nationalId,
"PatientIdentificationID": patientIdentificationId,
"OTP_SendType": otpSendType,
"LanguageID": languageId,
"VersionID": versionId,
"Channel": channel,
"IPAdress": ipAdress,
"generalid": generalid,
"PatientOutSA": patientOutSa,
"isDentalAllowedBackend": isDentalAllowedBackend,
"DeviceTypeID": deviceTypeId,
"Latitude": latitude,
"Longitude": longitude,
"PatientType": patientType,
};
}

@ -2,9 +2,11 @@ import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:hmg_patient_app_new/core/app_assets.dart';
import 'package:hmg_patient_app_new/core/dependencies.dart';
import 'package:hmg_patient_app_new/core/utils/utils.dart';
import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
import 'package:hmg_patient_app_new/services/navigation_service.dart';
import 'package:hmg_patient_app_new/theme/colors.dart';
import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart';
@ -22,6 +24,7 @@ class _QuickLogin extends State<QuickLogin> {
@override
Widget build(BuildContext context) {
NavigationService navigationService = getIt.get<NavigationService>();
return Container(
decoration: const BoxDecoration(
color: Colors.white,
@ -43,7 +46,7 @@ class _QuickLogin extends State<QuickLogin> {
children: [
InkWell(
onTap: () {
Navigator.pop(context, true);
navigationService.pop();
},
child: Utils.buildSvgWithAssets(icon: AppAssets.cross_circle)),
],

@ -114,7 +114,8 @@ class _SavedLogin extends State<SavedLogin> {
fontWeight: FontWeight.w500,
borderRadius: 12,
padding: EdgeInsets.fromLTRB(0, 10, 0, 10),
icon: AppAssets.sms,
icon: getTypeIcons(loginType.toInt), //loginType == LoginTypeEnum.sms ? AppAssets.sms :AppAssets.whatsapp,
iconColor: loginType != LoginTypeEnum.whatsapp ? Colors.white: null ,
),
),
],
@ -210,7 +211,8 @@ class _SavedLogin extends State<SavedLogin> {
textColor: AppColors.textColor,
borderWidth: 2,
padding: EdgeInsets.fromLTRB(0, 14, 0, 14),
icon: AppAssets.password_validation,
icon: AppAssets.sms,
iconColor: AppColors.textColor,
)
: Container(),
SizedBox(

@ -23,6 +23,7 @@ import 'package:hmg_patient_app_new/theme/colors.dart';
import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart';
import 'package:hmg_patient_app_new/widgets/common_bottom_sheet.dart';
import 'package:hmg_patient_app_new/widgets/custom_tab_bar.dart' show CustomTabBar;
import 'package:hmg_patient_app_new/widgets/loader/bottomsheet_loader.dart';
import 'package:hmg_patient_app_new/widgets/transitions/fade_page.dart';
import 'package:provider/provider.dart';
@ -322,14 +323,20 @@ class _LandingPageState extends State<LandingPage> {
}
void showQuickLogin(BuildContext context) {
showCommonBottomSheet(
showCommonBottomSheetWithoutHeight(
context,
title: "",
child: QuickLogin(
isCloseButtonVisible: false,
child:
StatefulBuilder(
builder: (context, setState) {
return QuickLogin(
isDone: isDone,
onPressed: () {
// sharedPref.setBool(HAS_ENABLED_QUICK_LOGIN, true);
authVM.loginWithFingerPrintFace((){
isDone = true;
setState(() {
@ -337,10 +344,11 @@ class _LandingPageState extends State<LandingPage> {
});
},
),
height: isDone == false ? ResponsiveExtension.screenHeight * 0.5 : ResponsiveExtension.screenHeight * 0.3,
);
}),
// height: isDone == false ? ResponsiveExtension.screenHeight * 0.5 : ResponsiveExtension.screenHeight * 0.3,
isFullScreen: false,
callBackFunc: (str) {
callBackFunc: () {
isDone = true;
setState(() {});
},

@ -126,7 +126,7 @@ void showCommonBottomSheetWithoutHeight(
top: false,
left: false,
right: false,
child: Container(
child:isCloseButtonVisible ? Container(
padding: EdgeInsets.only(left: 24, top: 24, right: 24, bottom: 12),
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.bottomSheetBgColor, borderRadius: 24.h),
child: Column(
@ -144,7 +144,7 @@ void showCommonBottomSheetWithoutHeight(
),
child,
],
)),
)) : child,
);
}).then((value) {
callBackFunc();

@ -0,0 +1,45 @@
import 'package:flutter/material.dart';
import 'package:get_it/get_it.dart';
import 'package:hmg_patient_app_new/core/dependencies.dart';
import 'package:hmg_patient_app_new/core/utils/utils.dart';
import 'package:hmg_patient_app_new/services/navigation_service.dart';
class LoaderBottomSheet {
static final NavigationService _navService = GetIt.I<NavigationService>();
static bool _isVisible = false;
static void showLoader() {
if (_isVisible) return;
_isVisible = true;
showModalBottomSheet(
context: _navService.navigatorKey.currentContext!,
isDismissible: false,
enableDrag: false,
backgroundColor: Colors.transparent,
builder: (_) {
return Container(
height: MediaQuery.of(_navService.navigatorKey.currentContext!).size.height * 0.3,
decoration: const BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.vertical(top: Radius.circular(16)),
),
child: Center(
child: Utils.getLoadingWidget(),
),
);
},
).whenComplete(() {
// reset state if dismissed by system
_isVisible = false;
});
}
static void hideLoader() {
if (_isVisible) {
Navigator.of(_navService.navigatorKey.currentContext!).pop();
_isVisible = false;
}
}
}
Loading…
Cancel
Save