import ' dart:convert ' ;
import ' dart:developer ' ;
import ' dart:io ' ;
import ' package:easy_localization/easy_localization.dart ' ;
import ' package:flutter/services.dart ' show rootBundle ;
import ' package:flutter/material.dart ' ;
import ' package:get_it/get_it.dart ' ;
import ' package:hijri_gregorian_calendar/hijri_gregorian_calendar.dart ' ;
import ' package:hmg_patient_app_new/core/app_state.dart ' ;
import ' package:hmg_patient_app_new/core/cache_consts.dart ' ;
import ' package:hmg_patient_app_new/core/common_models/nationality_country_model.dart ' ;
import ' package:hmg_patient_app_new/core/common_models/privilege/HMCProjectListModel.dart ' ;
import ' package:hmg_patient_app_new/core/common_models/privilege/PrivilegeModel.dart ' ;
import ' package:hmg_patient_app_new/core/common_models/privilege/ProjectDetailListModel.dart ' ;
import ' package:hmg_patient_app_new/core/common_models/privilege/VidaPlusProjectListModel.dart ' ;
import ' package:hmg_patient_app_new/core/dependencies.dart ' ;
import ' package:hmg_patient_app_new/core/enums.dart ' ;
import ' package:hmg_patient_app_new/core/utils/loading_utils.dart ' ;
import ' package:hmg_patient_app_new/core/utils/request_utils.dart ' ;
import ' package:hmg_patient_app_new/core/utils/utils.dart ' ;
import ' package:hmg_patient_app_new/core/utils/validation_utils.dart ' ;
import ' package:hmg_patient_app_new/extensions/context_extensions.dart ' ;
import ' package:hmg_patient_app_new/extensions/string_extensions.dart ' ;
import ' package:hmg_patient_app_new/features/authentication/authentication_repo.dart ' ;
import ' package:hmg_patient_app_new/features/authentication/models/request_models/check_activation_code_register_request_model.dart ' ;
import ' package:hmg_patient_app_new/features/authentication/models/request_models/registration_payload_model.dart ' ;
import ' package:hmg_patient_app_new/features/authentication/models/resp_models/authenticated_user_resp_model.dart ' ;
import ' package:hmg_patient_app_new/features/authentication/models/resp_models/check_activation_code_resp_model.dart ' ;
import ' package:hmg_patient_app_new/features/authentication/models/resp_models/check_user_staus_nhic_response_model.dart ' ;
import ' package:hmg_patient_app_new/features/authentication/models/resp_models/select_device_by_imei.dart ' ;
import ' package:hmg_patient_app_new/features/medical_file/medical_file_repo.dart ' ;
import ' package:hmg_patient_app_new/generated/locale_keys.g.dart ' ;
import ' package:hmg_patient_app_new/presentation/authentication/login.dart ' ;
import ' package:hmg_patient_app_new/presentation/authentication/saved_login_screen.dart ' ;
import ' package:hmg_patient_app_new/routes/app_routes.dart ' ;
import ' package:hmg_patient_app_new/services/cache_service.dart ' ;
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 ' package:hmg_patient_app_new/widgets/bottomsheet/exception_bottom_sheet.dart ' ;
import ' package:sms_otp_auto_verify/sms_otp_auto_verify.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 ' ;
class AuthenticationViewModel extends ChangeNotifier {
final AuthenticationRepo _authenticationRepo ;
final AppState _appState ;
final ErrorHandlerService _errorHandlerService ;
final DialogService _dialogService ;
final NavigationService _navigationService ;
final LocalAuthService _localAuthService ;
AuthenticationViewModel ( {
required AppState appState ,
required AuthenticationRepo authenticationRepo ,
required ErrorHandlerService errorHandlerService ,
required DialogService dialogService ,
required NavigationService navigationService ,
required CacheService cacheService ,
required LocalAuthService localAuthService ,
} ) : _navigationService = navigationService ,
_dialogService = dialogService ,
_errorHandlerService = errorHandlerService ,
_appState = appState ,
_authenticationRepo = authenticationRepo ,
_localAuthService = localAuthService ;
final TextEditingController nationalIdController = TextEditingController ( ) ,
phoneNumberController = TextEditingController ( ) ,
dobController = TextEditingController ( ) ,
nameController = TextEditingController ( ) ,
emailController = TextEditingController ( ) ;
CountryEnum selectedCountrySignup = CountryEnum . saudiArabia ;
MaritalStatusTypeEnum ? maritalStatus ;
GenderTypeEnum ? genderType ;
bool isTermsAccepted = false ;
List < NationalityCountries > ? countriesList ;
String ? dob = " " ;
final CacheService cacheService = GetIt . instance < CacheService > ( ) ;
NationalityCountries ? pickedCountryByUAEUser ;
CalenderEnum calenderType = CalenderEnum . gregorian ;
LoginTypeEnum loginTypeEnum = LoginTypeEnum . sms ;
final ValueNotifier < bool > otpScreenNotifier = ValueNotifier < bool > ( false ) ;
//==================
String errorMsg = ' ' ;
final FocusNode myFocusNode = FocusNode ( ) ;
var healthId ;
int getDeviceLastLogin = 1 ;
Future < void > onLoginPressed ( ) async {
try {
LoaderBottomSheet . showLoader ( ) ;
//TODO: We will remove this delay
// await Future.delayed(Duration(seconds: 3));
var data = _appState . getSelectDeviceByImeiRespModelElement ;
log ( " Cached IMEI data: ${ data ? . toJson ( ) } " ) ;
if ( data ! = null ) {
await _handleExistingImeiData ( data ) ;
} else {
await _handleNewImeiRegistration ( ) ;
}
} catch ( e ) {
log ( " Error in onLoginPressed: $ e " ) ;
LoaderBottomSheet . hideLoader ( ) ;
_dialogService . showErrorBottomSheet ( message: " An unexpected error occurred. Please try again. " , onOkPressed: ( ) { } ) ;
}
}
Future < void > clearDefaultInputValues ( ) async {
nationalIdController . clear ( ) ;
phoneNumberController . clear ( ) ;
emailController . clear ( ) ;
dobController . clear ( ) ;
maritalStatus = null ;
genderType = null ;
isTermsAccepted = false ;
selectedCountrySignup = CountryEnum . saudiArabia ;
pickedCountryByUAEUser = null ;
_appState . setUserRegistrationPayload = RegistrationDataModelPayload ( ) ;
_appState . setNHICUserData = CheckUserStatusResponseNHIC ( ) ;
}
void onCountryChange ( CountryEnum country ) {
selectedCountrySignup = country ;
notifyListeners ( ) ;
}
void onCalenderTypeChange ( bool isGregorian ) {
calenderType = isGregorian ? CalenderEnum . gregorian : CalenderEnum . hijri ;
notifyListeners ( ) ;
}
void onDobChange ( String ? date ) {
if ( calenderType = = CalenderEnum . hijri ) {
var hijriDate = HijriGregConverter . gregorianToHijri ( DateTime . parse ( date ! ) ) ;
DateTime hijriDateTimeForController = DateTime ( hijriDate . year , hijriDate . month , hijriDate . day ) ;
dob = Utils . formatDateForApi ( date ) ;
dobController . text = Utils . formatHijriDateToDisplay ( hijriDateTimeForController . toIso8601String ( ) ) ; // Or directly hijriDate.toString() if that's what your formatter expects
} else {
dobController . text = Utils . formatDateToDisplay ( date ! ) ;
dob = Utils . formatDateForApi ( date ) ;
}
notifyListeners ( ) ;
}
Future < void > loadCountriesData ( ) async {
final String response = await rootBundle . loadString ( ' assets/json/countriesList.json ' ) ;
final List < dynamic > data = json . decode ( response ) ;
countriesList = data . map ( ( e ) = > NationalityCountries . fromJson ( e ) ) . toList ( ) ;
}
void onMaritalStatusChange ( String ? status ) {
maritalStatus = MaritalStatusTypeExtension . fromType ( status ) ! ;
notifyListeners ( ) ;
}
void onGenderChange ( String ? status ) {
genderType = GenderTypeExtension . fromType ( status ) ! ;
notifyListeners ( ) ;
}
void clearEmailInput ( ) {
emailController . text = " " ;
}
void onUAEUserCountrySelection ( String ? value ) {
pickedCountryByUAEUser = countriesList ! . firstWhere ( ( element ) = > element . name = = value ) ;
notifyListeners ( ) ;
}
void onPhoneNumberChange ( String ? phoneNumber ) {
phoneNumberController . text = phoneNumber ! ;
}
void onTermAccepted ( ) {
isTermsAccepted = ! isTermsAccepted ;
notifyListeners ( ) ;
}
bool isUserFromUAE ( ) {
bool isFromUAE = false ;
if ( _appState . getUserRegistrationPayload . patientOutSa ! = 0 ) {
isFromUAE = true ;
}
return isFromUAE ;
}
void savePushTokenToAppState ( ) async {
_appState . deviceToken = await Utils . getStringFromPrefs ( CacheConst . pushToken ) ;
}
Future < void > selectDeviceImei ( { required Function ( dynamic data ) onSuccess , Function ( String ) ? onError } ) async {
// LoadingUtils.showFullScreenLoading();
// String firebaseToken = _appState.deviceToken;
String firebaseToken = await Utils . getStringFromPrefs ( CacheConst . pushToken ) ;
// String firebaseToken = "fY1fq_cITMmUCztA3UKKL9:APA91bEb2ZcdCPQPq3QsA0NW6a6btFvN-JjB1Pn3ZCoCzBMmVUhhh1ZQMtRn9tYPQ5G-jHDLiEpVAlBuRCVMkLDxa-zijsqbIui-4A-ynwclDWGFT4bUHTc";
// == ""
// ? "dOGRRszQQMGe_9wA5Hx3kO:APA91bFV5IcIJXvcCXXk0tc2ddtZgWwCPq7sGSuPr-YW7iiJpQZKgFGN9GAzCVOWL8MfheaP1slE8MdxB7lczdPBGdONQ7WbMmhgHcsUCUktq-hsapGXXqc"
// : _appState.deviceToken;
final result = await _authenticationRepo . selectDeviceByImei ( firebaseToken: firebaseToken ) ;
result . fold (
( failure ) async {
// LoadingUtils.hideFullScreenLoader();
// await _errorHandlerService.handleError(failure: failure);
LoaderBottomSheet . hideLoader ( ) ;
_navigationService . pushPage ( page: LoginScreen ( ) ) ;
} ,
( apiResponse ) {
// LoadingUtils.hideFullScreenLoader();
log ( " apiResponse: ${ apiResponse . data . toString ( ) } " ) ;
log ( " messageStatus: ${ apiResponse . messageStatus . toString ( ) } " ) ;
if ( apiResponse . messageStatus = = 1 ) {
onSuccess ( apiResponse . data ) ;
} else if ( apiResponse . messageStatus = = 2 ) {
_dialogService . showErrorBottomSheet ( message: " Message Status = 2 " , onOkPressed: ( ) { } ) ;
}
} ,
) ;
}
Future < void > _handleExistingImeiData ( dynamic data ) async {
try {
SelectDeviceByImeiRespModelElement ? savedData = _appState . getSelectDeviceByImeiRespModelElement ;
LoaderBottomSheet . hideLoader ( ) ;
if ( savedData ! = null ) {
// TODO: Navigate to SavedLogin when available
//_navigationService.pushPage(page: LoginScreen());
_navigationService . pushPage ( page: SavedLogin ( ) ) ;
}
} catch ( e ) {
log ( " Error handling existing IMEI data: $ e " ) ;
LoaderBottomSheet . hideLoader ( ) ;
_navigationService . pushPage ( page: LoginScreen ( ) ) ;
}
}
Future < void > _handleNewImeiRegistration ( ) async {
await selectDeviceImei ( onSuccess: ( dynamic respData ) async {
try {
if ( respData ! = null ) {
dynamic data = SelectDeviceByImeiRespModelElement . fromJson ( respData . toJson ( ) ) ;
_appState . setSelectDeviceByImeiRespModelElement ( data ) ;
LoaderBottomSheet . hideLoader ( ) ;
// TODO: Navigate to SavedLogin when available
// SelectDeviceByImeiRespModelElement savedData =
// SelectDeviceByImeiRespModelElement.fromJson(respData);
_navigationService . pushPage ( page: SavedLogin ( ) ) ;
// _navigationService.pushPage(page: LoginScreen());
} else {
print ( " print login........ " ) ;
LoaderBottomSheet . hideLoader ( ) ;
_navigationService . pushPage ( page: LoginScreen ( ) ) ;
}
} catch ( e ) {
log ( " Error processing IMEI registration response: $ e " ) ;
LoaderBottomSheet . hideLoader ( ) ;
_navigationService . pushPage ( page: LoginScreen ( ) ) ;
}
} , onError: ( String error ) {
LoaderBottomSheet . hideLoader ( ) ;
_dialogService . showErrorBottomSheet ( message: error , onOkPressed: ( ) { } ) ;
} ) ;
}
Future < void > checkUserAuthentication ( { required OTPTypeEnum otpTypeEnum , Function ( dynamic ) ? onSuccess , Function ( String ) ? onError } ) async {
// TODO: THIS SHOULD BE REMOVED LATER ON AND PASSED FROM APP STATE DIRECTLY INTO API CLIENT. BECAUSE THIS API ONLY NEEDS FEW PARAMS FROM USER
loginTypeEnum = otpTypeEnum = = OTPTypeEnum . sms ? LoginTypeEnum . sms : LoginTypeEnum . whatsapp ;
if ( phoneNumberController . text . isEmpty ) {
phoneNumberController . text = " 504278212 " ;
}
bool isValidated = ValidationUtils . isValidatePhoneAndId ( phoneNumber: phoneNumberController . text , nationalId: nationalIdController . text ) ;
if ( ! isValidated ) {
return ;
}
LoaderBottomSheet . showLoader ( ) ;
// LoadingUtils.showFullScreenLoader();
dynamic checkPatientAuthenticationReq = RequestUtils . getPatientAuthenticationRequest (
phoneNumber: phoneNumberController . text ,
nationId: nationalIdController . text ,
isForRegister: false ,
patientOutSA: false ,
otpTypeEnum: otpTypeEnum ,
patientId: 0 ,
zipCode: _appState . getSelectDeviceByImeiRespModelElement ! = null & & _appState . getSelectDeviceByImeiRespModelElement ! . outSa = = true
? CountryEnum . unitedArabEmirates . countryCode
: selectedCountrySignup . countryCode ,
calenderType: calenderType ) ;
final result = await _authenticationRepo . checkPatientAuthentication ( checkPatientAuthenticationReq: checkPatientAuthenticationReq ) ;
result . fold (
( failure ) async = > await _errorHandlerService . handleError (
failure: failure ,
onUnHandledFailure: ( failure ) async {
LoaderBottomSheet . hideLoader ( ) ;
await _dialogService . showCommonBottomSheetWithoutH (
message: failure . message ,
label: LocaleKeys . notice . tr ( ) ,
onOkPressed: ( ) {
_navigationService . pushAndReplace ( AppRoutes . register ) ;
} ,
onCancelPressed: ( ) {
_navigationService . pop ( ) ;
} ) ;
} ) ,
( 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 ' ] ;
await sendActivationCode ( otpTypeEnum: otpTypeEnum , phoneNumber: phoneNumberController . text , nationalIdOrFileNumber: nationalIdController . text , isForRegister: false ) ;
} else {
if ( apiResponse . data [ ' IsAuthenticated ' ] ) {
await checkActivationCode (
otpTypeEnum: otpTypeEnum ,
onWrongActivationCode: ( String ? message ) async {
await _dialogService . showCommonBottomSheetWithoutH (
message: message ? ? " " ,
label: LocaleKeys . notice . tr ( ) ,
onOkPressed: ( ) {
_navigationService . pop ( ) ;
} ) ;
} ,
activationCode: null , //todo silent login case halded on the repo itself..
) ;
}
}
}
} ,
) ;
}
Future < void > sendActivationCode (
{ required OTPTypeEnum otpTypeEnum ,
required String nationalIdOrFileNumber ,
required String phoneNumber ,
required bool isForRegister ,
dynamic payload ,
bool isComingFromResendOTP = false ,
bool isExcludedUser = false ,
bool isFormFamilyFile = false ,
int ? responseID } ) async {
var request = RequestUtils . getCommonRequestSendActivationCode (
otpTypeEnum: otpTypeEnum ,
mobileNumber: phoneNumber ,
selectedLoginType: otpTypeEnum . toInt ( ) ,
zipCode: selectedCountrySignup . countryCode ,
nationalId: int . parse ( nationalIdOrFileNumber ) ,
isFileNo: isForRegister ? isPatientHasFile ( request: payload ) : false ,
patientId: 0 ,
isForRegister: isForRegister ,
patientOutSA: isForRegister
? isPatientOutsideSA ( request: payload )
: selectedCountrySignup . countryCode = = CountryEnum . saudiArabia
? false
: true ,
payload: payload ,
isExcludedUser: isExcludedUser ,
isFormFamilyFile: isFormFamilyFile ,
responseID: responseID ) ;
// TODO: GET APP SMS SIGNATURE HERE
request . sMSSignature = await getSignature ( ) ;
if ( checkIsUserComingForRegister ( request: payload ) ) {
_appState . setUserRegistrationPayload = RegistrationDataModelPayload . fromJson ( payload ) ;
}
final resultEither = await _authenticationRepo . sendActivationCodeRepo (
sendActivationCodeReq: request , isRegister: checkIsUserComingForRegister ( request: payload ) , languageID: ' er ' , isFormFamilyFile: isFormFamilyFile ) ;
resultEither . fold (
( failure ) async = > await _errorHandlerService . handleError ( failure: failure ) ,
( apiResponse ) async {
int ? patientShareRequestID = 0 ;
if ( isFormFamilyFile ) {
patientShareRequestID = apiResponse . data [ ' PatientShareRequestID ' ] ;
}
if ( apiResponse . messageStatus = = 2 ) {
LoaderBottomSheet . hideLoader ( ) ;
await _dialogService . showCommonBottomSheetWithoutH (
message: apiResponse . errorMessage ? ? " Something Went Wrong " ,
onOkPressed: ( ) {
_navigationService . pop ( ) ;
} ) ;
} else {
if ( apiResponse . data ! = null & & apiResponse . data [ ' isSMSSent ' ] = = true ) {
LoaderBottomSheet . hideLoader ( ) ;
if ( ! isComingFromResendOTP ) {
navigateToOTPScreen (
otpTypeEnum: otpTypeEnum ,
phoneNumber: phoneNumber ,
isComingFromRegister: checkIsUserComingForRegister ( request: payload ) ,
payload: payload ,
isFormFamilyFile: isFormFamilyFile ,
isExcludedUser: isExcludedUser ,
responseID: responseID ,
patientShareRequestID: patientShareRequestID ,
) ;
}
} else {
// TODO: Handle isSMSSent false
// navigateToOTPScreen(otpTypeEnum: otpTypeEnum, phoneNumber: phoneNumber);
}
}
} ,
) ;
}
bool checkIsUserComingForRegister ( { required dynamic request } ) {
bool isUserComingForRegister = false ;
if ( request ! = null & & request [ ' isRegister ' ] = = true ) {
isUserComingForRegister = true ;
}
return isUserComingForRegister ;
}
Future < void > checkActivationCode (
{ required String ? activationCode ,
required OTPTypeEnum otpTypeEnum ,
required Function ( String ? message ) onWrongActivationCode ,
Function ( ) ? onResendActivation ,
bool isFormFamilyFile = false ,
dynamic patientShareRequestID ,
dynamic responseID } ) async {
bool isForRegister = ( _appState . getUserRegistrationPayload . healthId ! = null | | _appState . getUserRegistrationPayload . patientOutSa = = true | | _appState . getUserRegistrationPayload . patientOutSa = = 1 ) ;
final request = RequestUtils . getCommonRequestWelcome (
phoneNumber: phoneNumberController . text ,
otpTypeEnum: otpTypeEnum ,
deviceToken: _appState . deviceToken ,
// patientOutSA: _appState.getUserRegistrationPayload.projectOutSa == 1 ? true : false,
patientOutSA: isForRegister
? _appState . getUserRegistrationPayload . projectOutSa = = true
? true
: false
: _appState . getSelectDeviceByImeiRespModelElement ! = null
? _appState . getSelectDeviceByImeiRespModelElement ! . outSa !
: selectedCountrySignup = = CountryEnum . saudiArabia
? false
: true ,
loginTokenID: _appState . appAuthToken ,
registeredData: isForRegister ? _appState . getUserRegistrationPayload : null ,
nationIdText: nationalIdController . text ,
countryCode: _appState . getSelectDeviceByImeiRespModelElement ! = null & & _appState . getSelectDeviceByImeiRespModelElement ! . outSa = = true
? CountryEnum . unitedArabEmirates . countryCode
: selectedCountrySignup . countryCode ,
//TODO: Error Here IN Zip Code.
loginType: loginTypeEnum . toInt )
. toJson ( ) ;
LoaderBottomSheet . showLoader ( ) ;
if ( isForRegister ) {
if ( _appState . getUserRegistrationPayload . patientOutSa = = 0 ) request [ ' DOB ' ] = _appState . getUserRegistrationPayload . dob ;
request [ ' HealthId ' ] = _appState . getUserRegistrationPayload . healthId ;
request [ ' IsHijri ' ] = _appState . getUserRegistrationPayload . isHijri ;
request [ " PatientOutSA " ] = _appState . getUserRegistrationPayload . projectOutSa = = true ? 1 : 0 ;
request [ " ForRegisteration " ] = _appState . getUserRegistrationPayload . isRegister ;
request [ " isRegister " ] = false ;
final resultEither = await _authenticationRepo . checkActivationCodeRepo (
newRequest: request ,
activationCode: activationCode . toString ( ) ,
isRegister: true ,
) ;
LoaderBottomSheet . hideLoader ( ) ;
resultEither . fold (
( failure ) async = > await _errorHandlerService . handleError (
failure: failure ,
onUnHandledFailure: ( failure ) async {
LoaderBottomSheet . hideLoader ( ) ;
await _dialogService . showCommonBottomSheetWithoutH (
message: failure . message ,
label: LocaleKeys . notice . tr ( ) ,
onOkPressed: ( ) {
_navigationService . pop ( ) ;
} ) ;
} ) , ( apiResponse ) {
final activation = CheckActivationCode . fromJson ( apiResponse . data as Map < String , dynamic > ) ;
if ( _appState . getUserRegistrationPayload . isRegister = = true ) {
//TODO: KSA Version Came Hre
loadCountriesData ( ) ;
_navigationService . pushAndReplace ( AppRoutes . registerStepTwo ) ;
// Navigator.popUntil(context, (route) => Utils.route(route, equalsTo: RegisterNew));
return ;
}
} ) ;
} else {
final resultEither = await _authenticationRepo . checkActivationCodeRepo (
newRequest: CheckActivationCodeRegisterReq . fromJson ( request ) ,
activationCode: activationCode ,
isRegister: false ,
isFormFamilyFile: isFormFamilyFile ,
patientShareRequestID: patientShareRequestID ,
responseID: responseID ) ;
resultEither . fold (
( failure ) async = > await _errorHandlerService . handleError (
failure: failure ,
onUnHandledFailure: ( failure ) async {
LoaderBottomSheet . hideLoader ( ) ;
otpScreenNotifier . value = true ;
await _dialogService . showCommonBottomSheetWithoutH ( message: failure . message , label: LocaleKeys . notice . tr ( ) , onOkPressed: ( ) { } ) ;
} ,
onMessageStatusFailure: ( failure ) async {
LoaderBottomSheet . hideLoader ( ) ;
await _dialogService . showCommonBottomSheetWithoutH ( message: failure . message , label: LocaleKeys . notice . tr ( ) , onOkPressed: ( ) { } ) ;
} ) , ( apiResponse ) async {
print ( " API Response Data: ${ apiResponse . data } " ) ;
final activation = CheckActivationCode . fromJson ( apiResponse . data as Map < String , dynamic > ) ;
if ( activation . errorCode = = ' 699 ' ) {
// Todo: Hide Loader
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 ) ;
_appState . setPrivilegeModelList ( activation . list ! . first . listPrivilege ! ) ;
}
_appState . setUserBloodGroup = ( activation . patientBlodType ? ? " " ) ;
_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
if ( _appState . getSelectDeviceByImeiRespModelElement ! = null ) {
_appState . getSelectDeviceByImeiRespModelElement ! . logInType = loginTypeEnum . toInt ;
}
LoaderBottomSheet . hideLoader ( ) ;
insertPatientIMEIData ( loginTypeEnum . toInt ) ;
await clearDefaultInputValues ( ) ;
if ( isUserAgreedBefore ) {
navigateToHomeScreen ( ) ;
} else {
navigateToHomeScreen ( ) ;
//Agreement page not designed yet so we are navigating to home screen directly
// getUserAgreementContent(request: request);
}
// TODO: setPreferences and stuff
// sharedPref.remove(FAMILY_FILE);
// activation.list!.isFamily = false;
// userData = activation.list;
// sharedPref.setString(BLOOD_TYPE, activation.patientBloodType ?? "");
// authenticatedUserObject.user = activation.list!;
// projectViewModel.setPrivilege(privilegeList: res);
// await sharedPref.setObject(MAIN_USER, activation.list);
// await sharedPref.setObject(USER_PROFILE, activation.list);
// loginTokenID = activation.logInTokenID;
// await sharedPref.setObject(LOGIN_TOKEN_ID, activation.logInTokenID);
// await sharedPref.setString(TOKEN, activation.authenticationTokenID!);
// projectViewModel.analytics.loginRegistration.login_successful();
}
} ) ;
}
}
Future < bool > checkIfUserAgreedBefore ( { required dynamic request } ) async {
bool isAgreed = false ;
if ( havePrivilege ( 109 ) ) {
final resultEither = await _authenticationRepo . checkIfUserAgreed ( commonAuthanticatedRequest: request ) ;
resultEither . fold ( ( failure ) async = > await _errorHandlerService . handleError ( failure: failure ) , ( apiResponse ) {
if ( apiResponse . data [ ' IsPatientAlreadyAgreed ' ] ) {
return true ;
}
} ) ;
}
return isAgreed ;
}
Future < void > getUserAgreementContent ( { required dynamic request } ) async {
final resultEither = await _authenticationRepo . getUserAgreementContent ( commonAuthanticatedRequest: request ) ;
resultEither . fold ( ( failure ) async = > await _errorHandlerService . handleError ( failure: failure ) , ( apiResponse ) async {
// _navigationService.pushAndReplace(routeName)
//TODO: Add User Agreement Page Here
} ) ;
}
bool havePrivilege ( int id ) {
bool isHavePrivilege = false ;
try {
for ( var element in _appState . getAuthenticatedUser ( ) ! . listPrivilege ! ) {
if ( element . id = = id ) isHavePrivilege = element . previlege ! ;
}
} catch ( e ) {
print ( e ) ;
}
return isHavePrivilege ;
}
Future < void > navigateToHomeScreen ( ) async {
_navigationService . pushAndReplace ( AppRoutes . landingScreen ) ;
}
Future < void > navigateToOTPScreen (
{ required OTPTypeEnum otpTypeEnum ,
required String phoneNumber ,
required bool isComingFromRegister ,
dynamic payload ,
bool isFormFamilyFile = false ,
bool isExcludedUser = false ,
int ? responseID ,
int ? patientShareRequestID } ) async {
_navigationService . pushToOtpScreen (
phoneNumber: phoneNumber ,
isFormFamilyFile: isFormFamilyFile ,
checkActivationCode: ( int activationCode ) async {
await checkActivationCode (
activationCode: activationCode . toString ( ) ,
isFormFamilyFile: isFormFamilyFile ,
otpTypeEnum: otpTypeEnum ,
responseID: responseID ,
patientShareRequestID: patientShareRequestID ,
onWrongActivationCode: ( String ? value ) {
onWrongActivationCode ( message: value ) ;
} ,
) ;
} ,
onResendOTPPressed: ( String phoneNumber ) async {
await sendActivationCode (
otpTypeEnum: otpTypeEnum ,
phoneNumber: phoneNumberController . text ,
nationalIdOrFileNumber: nationalIdController . text ,
isForRegister: isComingFromRegister ,
isComingFromResendOTP: true ,
payload: payload ,
isFormFamilyFile: isFormFamilyFile ,
isExcludedUser: isExcludedUser ,
responseID: responseID ,
) ;
} ,
) ;
}
Future < void > onWrongActivationCode ( { String ? message } ) async {
otpScreenNotifier . value = true ;
await _dialogService . showErrorBottomSheet ( message: message ? ? " Something went wrong. " , onOkPressed: ( ) { } ) ;
}
loginWithFingerPrintFace ( Function success ) async {
_localAuthService . authenticate ( ) . then ( ( value ) async {
if ( value ) {
LoaderBottomSheet . showLoader ( ) ;
success ( ) ;
loginTypeEnum = ( _appState . deviceTypeID = = 1 ? LoginTypeEnum . face : LoginTypeEnum . fingerprint ) ;
if ( ! _appState . isAuthenticated ) {
//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 ) ;
} else {
// authenticated = true;
await insertPatientIMEIData ( loginTypeEnum . toInt ) ;
LoaderBottomSheet . hideLoader ( ) ;
}
notifyListeners ( ) ;
// navigateToHomeScreen();
} else {
//authenticated = false;
notifyListeners ( ) ;
}
} ) ;
}
checkLastLoginStatus ( Function ( ) onSuccess ) async {
Future . delayed ( Duration ( seconds: 1 ) , ( ) async {
if ( cacheService . getBool ( key: CacheConst . quickLoginEnabled ) = = null ) {
if ( _appState . getSelectDeviceByImeiRespModelElement ! = null & &
( _appState . getSelectDeviceByImeiRespModelElement ! . logInType = = 1 | | _appState . getSelectDeviceByImeiRespModelElement ! . logInType = = 4 ) ) {
phoneNumberController . text = ( _appState . getAuthenticatedUser ( ) ! . mobileNumber ! . startsWith ( " 0 " )
? _appState . getAuthenticatedUser ( ) ! . mobileNumber ! . replaceFirst ( " 0 " , " " )
: _appState . getAuthenticatedUser ( ) ! . mobileNumber ) ! ;
nationalIdController . text = _appState . getAuthenticatedUser ( ) ! . nationalityId ! ;
onSuccess ( ) ;
} else if ( ( loginTypeEnum = = LoginTypeEnum . sms | | loginTypeEnum = = LoginTypeEnum . whatsapp & & _appState . getSelectDeviceByImeiRespModelElement = = null ) & &
_appState . getAuthenticatedUser ( ) ! = null ) {
phoneNumberController . text = ( _appState . getAuthenticatedUser ( ) ! . mobileNumber ! . startsWith ( " 0 " )
? _appState . getAuthenticatedUser ( ) ! . mobileNumber ! . replaceFirst ( " 0 " , " " )
: _appState . getAuthenticatedUser ( ) ! . mobileNumber ) ! ;
nationalIdController . text = _appState . getAuthenticatedUser ( ) ! . nationalityId ! ;
onSuccess ( ) ;
}
}
} ) ;
}
Future < void > onRegistrationStart ( { required OTPTypeEnum otpTypeEnum } ) async {
bool isOutSidePatient = selectedCountrySignup . countryCode = = CountryEnum . unitedArabEmirates . countryCode ? true : false ;
LoaderBottomSheet . showLoader ( ) ;
final request = await RequestUtils . getPatientAuthenticationRequest (
phoneNumber: phoneNumberController . text ,
nationId: nationalIdController . text ,
patientOutSA: isOutSidePatient ,
otpTypeEnum: otpTypeEnum ,
isForRegister: true ,
patientId: 0 ,
zipCode: selectedCountrySignup . countryCode ,
calenderType: calenderType ,
dob: dob )
. toJson ( ) ;
var nRequest = Map < String , dynamic > . from ( request ) ;
if ( true ) {
request . removeWhere ( ( key , value ) = > value = = null ) ;
nRequest . removeWhere ( ( key , value ) = > value = = null ) ;
nRequest . removeWhere ( ( key , value ) = > key = = " SearchType " ) ;
nRequest . removeWhere ( ( key , value ) = > key = = " PatientID " ) ;
nRequest . removeWhere ( ( key , value ) = > key = = " OTP_SendType " ) ;
nRequest . removeWhere ( ( key , value ) = > key = = " LanguageID " ) ;
}
final resultEither = await _authenticationRepo . checkPatientForRegistration ( commonAuthanticatedRequest: nRequest ) ;
resultEither . fold ( ( failure ) async = > await _errorHandlerService . handleError ( failure: failure ) , ( apiResponse ) async {
checkUserStatusForRegistration ( response: apiResponse . data , request: request ) ;
} ) ;
}
Future < void > onRegistrationComplete ( ) async {
// LoaderBottomSheet.showLoader();
LoadingUtils . showFullScreenLoader ( loadingText: " Setting up your medical file. \n May take a moment. " ) ;
var request = RequestUtils . getUserSignupCompletionRequest ( fullName: nameController . text , emailAddress: emailController . text , gender: genderType , maritalStatus: maritalStatus ) ;
final resultEither = await _authenticationRepo . registerUser ( registrationPayloadDataModelRequest: request ) ;
resultEither . fold ( ( failure ) async = > await _errorHandlerService . handleError ( failure: failure ) , ( apiResponse ) async {
if ( apiResponse . data is String ) {
//TODO: This Section Need to Be Testing.
LoadingUtils . hideFullScreenLoader ( ) ;
_dialogService . showExceptionBottomSheet ( message: apiResponse . data , onOkPressed: ( ) { } , onCancelPressed: ( ) { } ) ;
//TODO: Here We Need to Show a Dialog Of Something in the case of Fail With OK and Cancel and the Display Variable WIll be result.
} else {
LoadingUtils . hideFullScreenLoader ( ) ;
if ( apiResponse . data [ " MessageStatus " ] = = 1 ) {
LoadingUtils . showFullScreenLoader ( isSuccessDialog: true ) ;
//TODO: Here We Need to Show a Dialog Of Something in the case of Success.
await clearDefaultInputValues ( ) ; // This will Clear All Default Values Of User.
Future . delayed ( Duration ( seconds: 1 ) , ( ) {
LoadingUtils . hideFullScreenLoader ( ) ;
_navigationService . pushAndReplace ( AppRoutes . loginScreen ) ;
} ) ;
}
}
} ) ;
return ;
}
Future < void > checkUserStatusForRegistration ( { required dynamic response , required dynamic request } ) async {
if ( response is Map ) {
if ( response [ " MessageStatus " ] = = 2 ) {
LoaderBottomSheet . hideLoader ( ) ;
print ( response [ " ErrorEndUserMessage " ] ) ;
return ;
}
if ( response [ ' hasFile ' ] = = true ) {
//TODO: Show Here Ok And Cancel Dialog and On OKPress it will go for sendActivationCode
LoaderBottomSheet . hideLoader ( ) ;
_dialogService . showCommonBottomSheetWithoutH (
message: response [ " ErrorMessage " ] ,
onOkPressed: ( ) async {
await clearDefaultInputValues ( ) ;
_navigationService . pushAndReplace ( AppRoutes . loginScreen ) ;
} ,
onCancelPressed: ( ) {
_navigationService . pop ( ) ;
} ) ;
} else {
request [ ' forRegister ' ] = true ;
request [ ' isRegister ' ] = true ;
_appState . setAppAuthToken = response [ ' LogInTokenID ' ] ;
if ( isPatientOutsideSA ( request: response ) ) {
print ( " =======OUT SA======= " ) ;
sendActivationCode (
otpTypeEnum: OTPTypeEnumExtension . fromInt ( request [ " OTP_SendType " ] ) ,
nationalIdOrFileNumber: request [ " PatientIdentificationID " ] . toString ( ) ,
phoneNumber: request [ " PatientMobileNumber " ] . toString ( ) ,
payload: request ,
isForRegister: true ,
) ;
} else {
print ( " =======IN SA======= " ) ;
chekUserNHICData ( request: request ) ;
}
}
} else {
//TODO: Here Hide Loader And Show TOAST
//TODO: if (response['ErrorCode'] == '-986') Toast With OK, And Show response as Output.
LoaderBottomSheet . hideLoader ( ) ;
_dialogService . showErrorBottomSheet ( message: response [ ' ErrorMessage ' ] ) ;
}
}
bool isPatientOutsideSA ( { required dynamic request } ) {
bool isOutSideSa = false ;
if ( request [ " PatientOutSA " ] = = true | | request [ " PatientOutSA " ] = = 1 ) {
isOutSideSa = true ;
} else {
isOutSideSa = false ;
}
return isOutSideSa ;
}
bool isPatientHasFile ( { required dynamic request } ) {
bool isFile = false ;
if ( request ! = null & & request [ " NationalID " ] ! = null ) {
isFile = request [ " NationalID " ] . length < 10 ;
}
return isFile ;
}
Future < void > chekUserNHICData ( { required dynamic request } ) async {
final resultEither = await _authenticationRepo . checkUserStatus ( commonAuthanticatedRequest: request ) ;
resultEither . fold ( ( failure ) async = > await _errorHandlerService . handleError ( failure: failure ) , ( apiResponse ) async {
if ( apiResponse . data is Map ) {
setNHICData ( apiResponse . data , request ) ;
sendActivationCode (
otpTypeEnum: OTPTypeEnumExtension . fromInt ( request [ " OTP_SendType " ] ) ,
nationalIdOrFileNumber: request [ " PatientIdentificationID " ] . toString ( ) ,
phoneNumber: request [ " PatientMobileNumber " ] . toString ( ) ,
payload: request ,
isForRegister: true ,
) ;
}
} ) ;
}
void setNHICData ( dynamic data , dynamic request ) {
_appState . setNHICUserData = CheckUserStatusResponseNHIC . fromJson ( data as Map < String , dynamic > ) ;
request [ " healthId " ] = _appState . getNHICUserData . healthId ;
_appState . setUserRegistrationPayload = RegistrationDataModelPayload . fromJson ( request ) ;
}
Future < void > insertPatientIMEIData ( int loginType ) async {
final resultEither = await _authenticationRepo . insertPatientIMEIData (
patientIMEIDataRequest: PatientInsertDeviceImei (
imei: _appState . deviceToken ,
deviceTypeId: _appState . getDeviceTypeID ( ) ,
patientId: _appState . getAuthenticatedUser ( ) ! . patientId ! ,
patientIdentificationNo: _appState . getAuthenticatedUser ( ) ! . patientIdentificationNo ! ,
identificationNo: _appState . getAuthenticatedUser ( ) ! . patientIdentificationNo ! ,
firstName: _appState . getAuthenticatedUser ( ) ! . firstName ! ,
lastName: _appState . getAuthenticatedUser ( ) ! . lastName ! ,
patientTypeId: _appState . getAuthenticatedUser ( ) ! . patientType ,
mobileNo: _appState . getAuthenticatedUser ( ) ! . mobileNumber ! ,
logInTypeId: loginType ,
patientOutSa: _appState . getAuthenticatedUser ( ) ! . outSa ! ,
outSa: _appState . getAuthenticatedUser ( ) ! . outSa = = 1 ? true : false ,
biometricEnabled: loginType = = 1 | | loginType = = 2 ? false : true ,
firstNameN: _appState . getAuthenticatedUser ( ) ! . firstNameN ,
lastNameN: _appState . getAuthenticatedUser ( ) ! . lastNameN ,
) . toJson ( ) ) ;
resultEither . fold ( ( failure ) async = > await _errorHandlerService . handleError ( failure: failure ) , ( apiResponse ) async {
if ( apiResponse . messageStatus = = 1 ) {
log ( " Insert IMEI Success " ) ;
insertPatientDeviceData ( loginType ) ;
} else {
log ( " Insert IMEI Failed " ) ;
}
} ) ;
}
Future < void > insertPatientDeviceData ( int loginType ) async {
final resultEither = await _authenticationRepo . insertPatientDeviceData (
patientDeviceDataRequest: InsertPatientMobileDeviceInfo (
deviceToken: _appState . deviceToken ,
deviceTypeId: _appState . getDeviceTypeID ( ) ,
patientId: _appState . getAuthenticatedUser ( ) ! . patientId ! ,
patientTypeId: _appState . getAuthenticatedUser ( ) ! . patientType ,
patientOutSa: _appState . getAuthenticatedUser ( ) ! . outSa ! ,
loginType: loginType ,
languageId: _appState . getLanguageID ( ) ,
latitude: _appState . userLat ,
longitude: _appState . userLong ,
voipToken: " " ,
deviceType: _appState . deviceTypeID ,
patientMobileNumber: _appState . getAuthenticatedUser ( ) ! . mobileNumber ,
nationalId: _appState . getAuthenticatedUser ( ) ! . patientIdentificationNo ,
gender: _appState . getAuthenticatedUser ( ) ! . gender )
. toJson ( ) ) ;
resultEither . fold ( ( failure ) async = > await _errorHandlerService . handleError ( failure: failure ) , ( apiResponse ) async {
if ( apiResponse . messageStatus = = 1 ) {
log ( " Insert Device Data Success " ) ;
} else {
log ( " Insert IMEI Failed " ) ;
}
} ) ;
}
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 . first [ ' LoginType ' ] ;
await checkActivationCode ( otpTypeEnum: OTPTypeEnum . faceIDFingerprint , activationCode: null , onWrongActivationCode: ( String ? message ) { } ) ;
await insertPatientIMEIData ( loginTypeEnum . toInt ) ;
LoaderBottomSheet . hideLoader ( ) ;
}
if ( apiResponse . messageStatus = = 2 ) {
LoaderBottomSheet . hideLoader ( ) ;
await _dialogService . showCommonBottomSheetWithoutH (
message: apiResponse . errorMessage ? ? " " ,
label: LocaleKeys . notice . tr ( ) ,
onOkPressed: ( ) {
_dialogService . showPhoneNumberPickerSheet (
label: " Where would you like to receive OTP? " ,
message: " Please select from the below options to receive OTP. " ,
onSMSPress: ( ) {
checkUserAuthentication ( otpTypeEnum: OTPTypeEnum . sms ) ;
} ,
onWhatsappPress: ( ) {
checkUserAuthentication ( otpTypeEnum: OTPTypeEnum . whatsapp ) ;
} ) ;
} ,
onCancelPressed: ( ) {
_navigationService . pop ( ) ;
} ) ;
}
} ) ;
}
@ override
void dispose ( ) {
nationalIdController . dispose ( ) ;
phoneNumberController . dispose ( ) ;
myFocusNode . dispose ( ) ;
super . dispose ( ) ;
}
Future < void > getServicePrivilege ( ) async {
final resultEither = await _authenticationRepo . getServicePrivilege ( ) ;
List < ListPrivilege > privilegeModelList = [ ] ;
List < VidaPlusProjectListModel > vidaPlusProjectListModel = [ ] ;
List < HMCProjectListModel > hMCProjectListModel = [ ] ;
List < ProjectDetailListModel > projectDetailListModel = [ ] ;
resultEither . fold (
( failure ) async = > await _errorHandlerService . handleError ( failure: failure ) ,
( apiResponse ) async {
if ( apiResponse . messageStatus = = 2 ) {
await _dialogService . showErrorBottomSheet ( message: apiResponse . errorMessage ? ? " ErrorEmpty " ) ;
} else {
apiResponse . data [ " ServicePrivilegeList " ] . forEach ( ( v ) {
privilegeModelList . add ( ListPrivilege . fromJson ( v ) ) ;
} ) ;
_appState . setPrivilegeModelList ( privilegeModelList . cast < ListPrivilege > ( ) ) ;
apiResponse . data [ " ProjectListVidaPlus " ] . forEach ( ( v ) {
vidaPlusProjectListModel . add ( VidaPlusProjectListModel . fromJson ( v ) ) ;
} ) ;
_appState . setVidaPlusProjectList ( vidaPlusProjectListModel ) ;
apiResponse . data [ " HMCProjectList " ] . forEach ( ( v ) {
hMCProjectListModel . add ( HMCProjectListModel . fromJson ( v ) ) ;
} ) ;
_appState . setHMCProjectList ( hMCProjectListModel ) ;
apiResponse . data [ " ProjectDetailList " ] . forEach ( ( v ) {
projectDetailListModel . add ( ProjectDetailListModel . fromJson ( v ) ) ;
} ) ;
_appState . setProjectsDetailList ( projectDetailListModel ) ;
}
} ,
) ;
}
Future < String ? > getSignature ( ) async {
if ( Platform . isAndroid ) {
return await SmsVerification . getAppSignature ( ) ;
} else {
return null ;
}
}
}