Merge branch 'master' into haroon_dev

# Conflicts:
#	lib/features/authentication/authentication_view_model.dart
#	lib/presentation/home/landing_page.dart
#	lib/presentation/lab/lab_orders_page.dart
pull/28/head
haroon amjad 2 months ago
commit f812dac059

@ -726,7 +726,7 @@ const DEACTIVATE_ACCOUNT = 'Services/Patients.svc/REST/PatientAppleActivation_In
class ApiConsts { class ApiConsts {
static const maxSmallScreen = 660; 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 // 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 insertPatientDeviceIMEIData = 'Services/Patients.svc/REST/Patient_INSERTDeviceIMEI';
static final String insertPatientMobileData = 'Services/MobileNotifications.svc/REST/Insert_PatientMobileDeviceInfo'; static final String insertPatientMobileData = 'Services/MobileNotifications.svc/REST/Insert_PatientMobileDeviceInfo';
static final String getPatientMobileData = '/Services/Authentication.svc/REST/GetMobileLoginInfo';
static final String getPrivileges = 'Services/Patients.svc/REST/Service_Privilege'; static final String getPrivileges = 'Services/Patients.svc/REST/Service_Privilege';
// static values for Api // static values for Api
static final double appVersionID = 18.7; 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>>> insertPatientIMEIData({required dynamic patientIMEIDataRequest});
Future<Either<Failure, GenericApiModel<dynamic>>> insertPatientDeviceData({required dynamic patientDeviceDataRequest}); Future<Either<Failure, GenericApiModel<dynamic>>> insertPatientDeviceData({required dynamic patientDeviceDataRequest});
Future<Either<Failure, GenericApiModel<dynamic>>> getPatientDeviceData({required dynamic patientDeviceDataRequest});
} }
class AuthenticationRepoImp implements AuthenticationRepo { class AuthenticationRepoImp implements AuthenticationRepo {
@ -456,4 +458,39 @@ class AuthenticationRepoImp implements AuthenticationRepo {
return Future.value(Left(UnknownFailure(e.toString()))); 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/error_handler_service.dart';
import 'package:hmg_patient_app_new/services/localauth_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/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/insert_patient_mobile_deviceinfo.dart';
import 'models/request_models/patient_insert_device_imei_request.dart'; import 'models/request_models/patient_insert_device_imei_request.dart';
@ -78,10 +80,11 @@ class AuthenticationViewModel extends ChangeNotifier {
String errorMsg = ''; String errorMsg = '';
final FocusNode myFocusNode = FocusNode(); final FocusNode myFocusNode = FocusNode();
var healthId; var healthId;
int getDeviceLastLogin =1;
Future<void> onLoginPressed() async { Future<void> onLoginPressed() async {
try { try {
LoadingUtils.showFullScreenLoader(); LoaderBottomSheet.showLoader();
//TODO: We will remove this delay //TODO: We will remove this delay
// await Future.delayed(Duration(seconds: 3)); // await Future.delayed(Duration(seconds: 3));
var data = _appState.getSelectDeviceByImeiRespModelElement; var data = _appState.getSelectDeviceByImeiRespModelElement;
@ -93,7 +96,7 @@ class AuthenticationViewModel extends ChangeNotifier {
} }
} catch (e) { } catch (e) {
log("Error in onLoginPressed: $e"); log("Error in onLoginPressed: $e");
LoadingUtils.hideFullScreenLoader(); LoaderBottomSheet.hideLoader();
_dialogService.showErrorBottomSheet(message: "An unexpected error occurred. Please try again.", onOkPressed: () {}); _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 { Future<void> _handleExistingImeiData(dynamic data) async {
try { try {
SelectDeviceByImeiRespModelElement? savedData = _appState.getSelectDeviceByImeiRespModelElement; SelectDeviceByImeiRespModelElement? savedData = _appState.getSelectDeviceByImeiRespModelElement;
LoadingUtils.hideFullScreenLoader(); LoaderBottomSheet.hideLoader();
if (savedData != null) { if (savedData != null) {
// TODO: Navigate to SavedLogin when available // TODO: Navigate to SavedLogin when available
@ -216,7 +219,7 @@ class AuthenticationViewModel extends ChangeNotifier {
} }
} catch (e) { } catch (e) {
log("Error handling existing IMEI data: $e"); log("Error handling existing IMEI data: $e");
LoadingUtils.hideFullScreenLoader(); LoaderBottomSheet.hideLoader();
_navigationService.pushPage(page: LoginScreen()); _navigationService.pushPage(page: LoginScreen());
} }
} }
@ -227,7 +230,7 @@ class AuthenticationViewModel extends ChangeNotifier {
if (respData != null) { if (respData != null) {
dynamic data = SelectDeviceByImeiRespModelElement.fromJson(respData.toJson()); dynamic data = SelectDeviceByImeiRespModelElement.fromJson(respData.toJson());
_appState.setSelectDeviceByImeiRespModelElement(data); _appState.setSelectDeviceByImeiRespModelElement(data);
LoadingUtils.hideFullScreenLoader(); LoaderBottomSheet.hideLoader();
// TODO: Navigate to SavedLogin when available // TODO: Navigate to SavedLogin when available
// SelectDeviceByImeiRespModelElement savedData = // SelectDeviceByImeiRespModelElement savedData =
@ -235,16 +238,16 @@ class AuthenticationViewModel extends ChangeNotifier {
_navigationService.pushPage(page: SavedLogin()); _navigationService.pushPage(page: SavedLogin());
// _navigationService.pushPage(page: LoginScreen()); // _navigationService.pushPage(page: LoginScreen());
} else { } else {
LoadingUtils.hideFullScreenLoader(); LoaderBottomSheet.hideLoader();
_navigationService.pushPage(page: LoginScreen()); _navigationService.pushPage(page: LoginScreen());
} }
} catch (e) { } catch (e) {
log("Error processing IMEI registration response: $e"); log("Error processing IMEI registration response: $e");
LoadingUtils.hideFullScreenLoader(); LoaderBottomSheet.hideLoader();
_navigationService.pushPage(page: LoginScreen()); _navigationService.pushPage(page: LoginScreen());
} }
}, onError: (String error) { }, onError: (String error) {
LoadingUtils.hideFullScreenLoader(); LoaderBottomSheet.hideLoader();
_dialogService.showErrorBottomSheet(message: error, onOkPressed: () {}); _dialogService.showErrorBottomSheet(message: error, onOkPressed: () {});
}); });
} }
@ -265,8 +268,8 @@ class AuthenticationViewModel extends ChangeNotifier {
if (!isValidated) { if (!isValidated) {
return; return;
} }
LoaderBottomSheet.showLoader();
LoadingUtils.showFullScreenLoader(); // LoadingUtils.showFullScreenLoader();
dynamic checkPatientAuthenticationReq = RequestUtils.getPatientAuthenticationRequest( dynamic checkPatientAuthenticationReq = RequestUtils.getPatientAuthenticationRequest(
phoneNumber: phoneNumberController.text, phoneNumber: phoneNumberController.text,
@ -279,20 +282,22 @@ class AuthenticationViewModel extends ChangeNotifier {
calenderType: calenderType); calenderType: calenderType);
final result = await _authenticationRepo.checkPatientAuthentication(checkPatientAuthenticationReq: checkPatientAuthenticationReq); final result = await _authenticationRepo.checkPatientAuthentication(checkPatientAuthenticationReq: checkPatientAuthenticationReq);
LoadingUtils.hideFullScreenLoader();
result.fold( result.fold(
(failure) async => await _errorHandlerService.handleError(failure: failure), (failure) async => await _errorHandlerService.handleError(failure: failure),
(apiResponse) async { (apiResponse) async {
if (apiResponse.messageStatus == 2) { if (apiResponse.messageStatus == 2) {
LoaderBottomSheet.hideLoader();
await _dialogService.showErrorBottomSheet(message: apiResponse.errorMessage ?? "ErrorEmpty", onOkPressed: () {}); await _dialogService.showErrorBottomSheet(message: apiResponse.errorMessage ?? "ErrorEmpty", onOkPressed: () {});
} else if (apiResponse.messageStatus == 1) { } else if (apiResponse.messageStatus == 1) {
if (apiResponse.data['isSMSSent']) { if (apiResponse.data['isSMSSent']) {
_appState.setAppAuthToken = apiResponse.data['LogInTokenID']; _appState.setAppAuthToken = apiResponse.data['LogInTokenID'];
sendActivationCode( await sendActivationCode(
otpTypeEnum: otpTypeEnum, otpTypeEnum: otpTypeEnum,
phoneNumber: phoneNumberController.text, phoneNumber: phoneNumberController.text,
nationalIdOrFileNumber: nationalIdController.text, nationalIdOrFileNumber: nationalIdController.text,
); );
} else { } else {
if (apiResponse.data['IsAuthenticated']) { if (apiResponse.data['IsAuthenticated']) {
await checkActivationCode( await checkActivationCode(
@ -300,6 +305,7 @@ class AuthenticationViewModel extends ChangeNotifier {
onWrongActivationCode: (String? message) {}, onWrongActivationCode: (String? message) {},
activationCode: null, //todo silent login case halded on the repo itself.. 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), (failure) async => await _errorHandlerService.handleError(failure: failure),
(apiResponse) async { (apiResponse) async {
if (apiResponse.messageStatus == 2) { if (apiResponse.messageStatus == 2) {
LoaderBottomSheet.hideLoader();
await _dialogService.showErrorBottomSheet(message: apiResponse.errorMessage ?? "ErrorEmpty"); await _dialogService.showErrorBottomSheet(message: apiResponse.errorMessage ?? "ErrorEmpty");
} else { } else {
if (apiResponse.data != null && apiResponse.data['isSMSSent'] == true) { if (apiResponse.data != null && apiResponse.data['isSMSSent'] == true) {
LoaderBottomSheet.hideLoader();
navigateToOTPScreen(otpTypeEnum: otpTypeEnum, phoneNumber: phoneNumber); navigateToOTPScreen(otpTypeEnum: otpTypeEnum, phoneNumber: phoneNumber);
} else { } else {
// TODO: Handle isSMSSent false // TODO: Handle isSMSSent false
@ -384,7 +392,7 @@ class AuthenticationViewModel extends ChangeNotifier {
countryCode: selectedCountrySignup.countryCode, countryCode: selectedCountrySignup.countryCode,
loginType: loginTypeEnum.toInt) loginType: loginTypeEnum.toInt)
.toJson(); .toJson();
LoaderBottomSheet.showLoader();
bool isForRegister = (_appState.getUserRegistrationPayload.healthId != null || _appState.getUserRegistrationPayload.patientOutSa == true); bool isForRegister = (_appState.getUserRegistrationPayload.healthId != null || _appState.getUserRegistrationPayload.patientOutSa == true);
if (isForRegister) { if (isForRegister) {
if (_appState.getUserRegistrationPayload.patientOutSa == true) request['DOB'] = _appState.getUserRegistrationPayload.dob; 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); final resultEither = await _authenticationRepo.checkActivationCodeRepo(newRequest: request, activationCode: activationCode.toString(), isRegister: true);
LoaderBottomSheet.hideLoader();
resultEither.fold((failure) async => await _errorHandlerService.handleError(failure: failure), (apiResponse) { resultEither.fold((failure) async => await _errorHandlerService.handleError(failure: failure), (apiResponse) {
final activation = CheckActivationCode.fromJson(apiResponse.data as Map<String, dynamic>); final activation = CheckActivationCode.fromJson(apiResponse.data as Map<String, dynamic>);
if (_appState.getUserRegistrationPayload.isRegister == true) { if (_appState.getUserRegistrationPayload.isRegister == true) {
@ -412,19 +422,26 @@ class AuthenticationViewModel extends ChangeNotifier {
resultEither.fold((failure) async => await _errorHandlerService.handleError(failure: failure), (apiResponse) async { resultEither.fold((failure) async => await _errorHandlerService.handleError(failure: failure), (apiResponse) async {
final activation = CheckActivationCode.fromJson(apiResponse.data as Map<String, dynamic>); final activation = CheckActivationCode.fromJson(apiResponse.data as Map<String, dynamic>);
if (activation.errorCode == '699') { if (activation.errorCode == '699') {
// Todo: Hide Loader // Todo: Hide Loader
// GifLoaderDialogUtils.hideDialog(context); // GifLoaderDialogUtils.hideDialog(context);
LoaderBottomSheet.hideLoader();
onWrongActivationCode(activation.errorEndUserMessage); onWrongActivationCode(activation.errorEndUserMessage);
return; return;
} else if (activation.messageStatus == 2) { } else if (activation.messageStatus == 2) {
LoaderBottomSheet.hideLoader();
onWrongActivationCode(activation.errorEndUserMessage); onWrongActivationCode(activation.errorEndUserMessage);
return; return;
} else if (_appState.getUserRegistrationPayload.isRegister == true) { } else if (_appState.getUserRegistrationPayload.isRegister == true) {
LoaderBottomSheet.hideLoader();
_navigationService.pushAndReplace(AppRoutes.registerStepTwo); _navigationService.pushAndReplace(AppRoutes.registerStepTwo);
// Navigator.popUntil(context, (route) => Utils.route(route, equalsTo: RegisterNew)); // Navigator.popUntil(context, (route) => Utils.route(route, equalsTo: RegisterNew));
return; return;
} else { } else {
if (activation.list != null && activation.list!.isNotEmpty) { if (activation.list != null && activation.list!.isNotEmpty) {
_appState.setAuthenticatedUser(activation.list!.first); _appState.setAuthenticatedUser(activation.list!.first);
} }
@ -432,6 +449,11 @@ class AuthenticationViewModel extends ChangeNotifier {
_appState.setAppAuthToken = activation.authenticationTokenId; _appState.setAppAuthToken = activation.authenticationTokenId;
final request = RequestUtils.getAuthanticatedCommonRequest().toJson(); final request = RequestUtils.getAuthanticatedCommonRequest().toJson();
bool isUserAgreedBefore = await checkIfUserAgreedBefore(request: request); 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); insertPatientIMEIData(loginTypeEnum.toInt);
clearDefaultInputValues(); clearDefaultInputValues();
if (isUserAgreedBefore) { if (isUserAgreedBefore) {
@ -518,20 +540,22 @@ class AuthenticationViewModel extends ChangeNotifier {
await _dialogService.showErrorBottomSheet(message: message ?? "Something went wrong. ", onOkPressed: () {}); await _dialogService.showErrorBottomSheet(message: message ?? "Something went wrong. ", onOkPressed: () {});
} }
loginWithFingerPrintFace() async { loginWithFingerPrintFace(Function success) async {
_localAuthService.authenticate().then((value) async { _localAuthService.authenticate().then((value) async {
if (value) { if (value) {
// we have to handle this if verification true; LoaderBottomSheet.showLoader();
success();
loginTypeEnum = (_appState.deviceTypeID == 1 ? LoginTypeEnum.face : LoginTypeEnum.fingerprint);
if (!_appState.isAuthenticated) { if (!_appState.isAuthenticated) {
loginTypeEnum = (_appState.deviceTypeID == 1 ? LoginTypeEnum.face : LoginTypeEnum.fingerprint); //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
print(loginTypeEnum); // await getPatientDeviceData(loginTypeEnum.toInt);
await checkActivationCode(otpTypeEnum: OTPTypeEnum.faceIDFingerprint, activationCode: null, onWrongActivationCode: (String? message) {}); await checkActivationCode(otpTypeEnum: OTPTypeEnum.faceIDFingerprint, activationCode: null, onWrongActivationCode: (String? message) {});
insertPatientIMEIData((_appState.deviceTypeID == 1 ? LoginTypeEnum.face.toInt : LoginTypeEnum.fingerprint.toInt)); await insertPatientIMEIData(loginTypeEnum.toInt);
} else { } else {
// authenticated = true; // authenticated = true;
insertPatientIMEIData((_appState.deviceTypeID == 1 ? LoginTypeEnum.face.toInt : LoginTypeEnum.fingerprint.toInt)); await insertPatientIMEIData(loginTypeEnum.toInt);
} }
LoaderBottomSheet.hideLoader();
notifyListeners(); notifyListeners();
// navigateToHomeScreen(); // navigateToHomeScreen();
} else { } else {
@ -760,6 +784,33 @@ class AuthenticationViewModel extends ChangeNotifier {
log("Insert IMEI Failed"); 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['LoginType'];
}
});
} }
@override @override

@ -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/material.dart';
import 'package:flutter_svg/flutter_svg.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/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/core/utils/utils.dart';
import 'package:hmg_patient_app_new/extensions/string_extensions.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/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/theme/colors.dart';
import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart'; import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart';
@ -22,6 +24,7 @@ class _QuickLogin extends State<QuickLogin> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
NavigationService navigationService = getIt.get<NavigationService>();
return Container( return Container(
decoration: const BoxDecoration( decoration: const BoxDecoration(
color: Colors.white, color: Colors.white,
@ -43,7 +46,7 @@ class _QuickLogin extends State<QuickLogin> {
children: [ children: [
InkWell( InkWell(
onTap: () { onTap: () {
Navigator.pop(context, true); navigationService.pop();
}, },
child: Utils.buildSvgWithAssets(icon: AppAssets.cross_circle)), child: Utils.buildSvgWithAssets(icon: AppAssets.cross_circle)),
], ],
@ -101,9 +104,6 @@ class _QuickLogin extends State<QuickLogin> {
text:LocaleKeys.enableQuickLogin.tr(), text:LocaleKeys.enableQuickLogin.tr(),
onPressed: () { onPressed: () {
widget.onPressed(); widget.onPressed();
setState(() {
});
}, },
backgroundColor: Color(0xffED1C2B), backgroundColor: Color(0xffED1C2B),
borderColor: Color(0xffED1C2B), borderColor: Color(0xffED1C2B),

@ -42,7 +42,7 @@ class _SavedLogin extends State<SavedLogin> {
authVm.nationalIdController.text = appState.getSelectDeviceByImeiRespModelElement!.identificationNo!; authVm.nationalIdController.text = appState.getSelectDeviceByImeiRespModelElement!.identificationNo!;
if (loginType == LoginTypeEnum.fingerprint || loginType == LoginTypeEnum.face) { if (loginType == LoginTypeEnum.fingerprint || loginType == LoginTypeEnum.face) {
authVm.loginWithFingerPrintFace(); authVm.loginWithFingerPrintFace((){});
} }
super.initState(); super.initState();
@ -101,7 +101,7 @@ class _SavedLogin extends State<SavedLogin> {
text: "${LocaleKeys.loginBy.tr()} ${loginType.displayName}", text: "${LocaleKeys.loginBy.tr()} ${loginType.displayName}",
onPressed: () { onPressed: () {
if (loginType == LoginTypeEnum.fingerprint || loginType == LoginTypeEnum.face) { if (loginType == LoginTypeEnum.fingerprint || loginType == LoginTypeEnum.face) {
authVm.loginWithFingerPrintFace(); authVm.loginWithFingerPrintFace((){});
} else { } else {
// int? val = loginType.toInt; // int? val = loginType.toInt;
authVm.checkUserAuthentication(otpTypeEnum: loginType == LoginTypeEnum.sms ? OTPTypeEnum.sms : OTPTypeEnum.whatsapp); authVm.checkUserAuthentication(otpTypeEnum: loginType == LoginTypeEnum.sms ? OTPTypeEnum.sms : OTPTypeEnum.whatsapp);
@ -114,7 +114,8 @@ class _SavedLogin extends State<SavedLogin> {
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
borderRadius: 12, borderRadius: 12,
padding: EdgeInsets.fromLTRB(0, 10, 0, 10), 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, textColor: AppColors.textColor,
borderWidth: 2, borderWidth: 2,
padding: EdgeInsets.fromLTRB(0, 14, 0, 14), padding: EdgeInsets.fromLTRB(0, 14, 0, 14),
icon: AppAssets.password_validation, icon: AppAssets.sms,
iconColor: AppColors.textColor,
) )
: Container(), : Container(),
SizedBox( SizedBox(
@ -224,7 +226,7 @@ class _SavedLogin extends State<SavedLogin> {
iconColor: null, iconColor: null,
onPressed: () { onPressed: () {
if (loginType == LoginTypeEnum.fingerprint || loginType == LoginTypeEnum.face) { if (loginType == LoginTypeEnum.fingerprint || loginType == LoginTypeEnum.face) {
authVm.loginWithFingerPrintFace(); authVm.loginWithFingerPrintFace((){});
} else { } else {
loginType = LoginTypeEnum.whatsapp; loginType = LoginTypeEnum.whatsapp;
int? val = loginType.toInt; int? val = loginType.toInt;

@ -26,6 +26,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/buttons/custom_button.dart';
import 'package:hmg_patient_app_new/widgets/common_bottom_sheet.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/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:hmg_patient_app_new/widgets/transitions/fade_page.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
@ -38,6 +39,7 @@ class LandingPage extends StatefulWidget {
class _LandingPageState extends State<LandingPage> { class _LandingPageState extends State<LandingPage> {
late final AuthenticationViewModel authVM; late final AuthenticationViewModel authVM;
bool isDone = false;
late final HabibWalletViewModel habibWalletVM; late final HabibWalletViewModel habibWalletVM;
late AppState appState; late AppState appState;
@ -49,7 +51,7 @@ class _LandingPageState extends State<LandingPage> {
authVM.savePushTokenToAppState(); authVM.savePushTokenToAppState();
if (mounted) { if (mounted) {
authVM.checkLastLoginStatus(() { authVM.checkLastLoginStatus(() {
showQuickLogin(context, false); showQuickLogin(context);
}); });
} }
scheduleMicrotask(() { scheduleMicrotask(() {
@ -334,20 +336,33 @@ class _LandingPageState extends State<LandingPage> {
); );
} }
void showQuickLogin(BuildContext context, bool isDone) { void showQuickLogin(BuildContext context) {
showCommonBottomSheet( showCommonBottomSheetWithoutHeight(
context, context,
title: "", title: "",
child: QuickLogin( isCloseButtonVisible: false,
child:
StatefulBuilder(
builder: (context, setState) {
return QuickLogin(
isDone: isDone, isDone: isDone,
onPressed: () { onPressed: () {
// sharedPref.setBool(HAS_ENABLED_QUICK_LOGIN, true); // sharedPref.setBool(HAS_ENABLED_QUICK_LOGIN, true);
authVM.loginWithFingerPrintFace(); authVM.loginWithFingerPrintFace((){
isDone = true;
setState(() {
});
});
}, },
), );
height: isDone == false ? ResponsiveExtension.screenHeight * 0.5 : ResponsiveExtension.screenHeight * 0.3, }),
// height: isDone == false ? ResponsiveExtension.screenHeight * 0.5 : ResponsiveExtension.screenHeight * 0.3,
isFullScreen: false, isFullScreen: false,
callBackFunc: (str) { callBackFunc: () {
isDone = true; isDone = true;
setState(() {}); setState(() {});
}, },

@ -5,18 +5,22 @@ import 'package:flutter/material.dart';
import 'package:hmg_patient_app_new/core/app_assets.dart'; import 'package:hmg_patient_app_new/core/app_assets.dart';
import 'package:hmg_patient_app_new/core/app_export.dart'; import 'package:hmg_patient_app_new/core/app_export.dart';
import 'package:hmg_patient_app_new/core/utils/utils.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/extensions/widget_extensions.dart'; import 'package:hmg_patient_app_new/extensions/widget_extensions.dart';
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart'; import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
import 'package:hmg_patient_app_new/theme/colors.dart'; import 'package:hmg_patient_app_new/theme/colors.dart';
import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart';
class CollapsingListView extends StatelessWidget { class CollapsingListView extends StatelessWidget {
final String title; final String title;
Widget? child; Widget? child;
VoidCallback? search; VoidCallback? search;
VoidCallback? report;
VoidCallback? logout;
Widget? bottomChild; Widget? bottomChild;
bool isClose; bool isClose;
CollapsingListView({required this.title, this.child, this.search, this.isClose = false, this.bottomChild}); CollapsingListView({required this.title, this.child, this.search, this.isClose = false, this.bottomChild, this.report, this.logout});
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -30,6 +34,7 @@ class CollapsingListView extends StatelessWidget {
pinned: true, pinned: true,
expandedHeight: 100, expandedHeight: 100,
stretch: true, stretch: true,
surfaceTintColor: Colors.transparent,
backgroundColor: AppColors.bgScaffoldColor, backgroundColor: AppColors.bgScaffoldColor,
leading: IconButton( leading: IconButton(
icon: Utils.buildSvgWithAssets(icon: isClose ? AppAssets.closeBottomNav : AppAssets.arrow_back, width: 32.h, height: 32.h), icon: Utils.buildSvgWithAssets(icon: isClose ? AppAssets.closeBottomNav : AppAssets.arrow_back, width: 32.h, height: 32.h),
@ -44,6 +49,7 @@ class CollapsingListView extends StatelessWidget {
t = t - 1; t = t - 1;
if (t < 0.7) t = 0.7; if (t < 0.7) t = 0.7;
t = t.clamp(0.0, 1.0); t = t.clamp(0.0, 1.0);
print("t:$t");
final double fontSize = lerpDouble(14, 18, t)!; final double fontSize = lerpDouble(14, 18, t)!;
final double bottomPadding = lerpDouble(0, 0, t)!; final double bottomPadding = lerpDouble(0, 0, t)!;
@ -58,10 +64,7 @@ class CollapsingListView extends StatelessWidget {
t, t,
)!, )!,
child: Padding( child: Padding(
padding: EdgeInsets.only( padding: EdgeInsets.only(left: leftPadding, bottom: bottomPadding),
left: leftPadding,
bottom: bottomPadding,
),
child: Row( child: Row(
spacing: 4.h, spacing: 4.h,
children: [ children: [
@ -78,6 +81,8 @@ class CollapsingListView extends StatelessWidget {
color: AppColors.blackColor, color: AppColors.blackColor,
letterSpacing: -0.5), letterSpacing: -0.5),
).expanded, ).expanded,
if (logout != null) actionButton(context, t, title: "Logout".needTranslation, icon: AppAssets.report_icon).onPress(logout!),
if (report != null) actionButton(context, t, title: "Report".needTranslation, icon: AppAssets.report_icon).onPress(report!),
if (search != null) Utils.buildSvgWithAssets(icon: AppAssets.search_icon).onPress(search!).paddingOnly(right: 24) if (search != null) Utils.buildSvgWithAssets(icon: AppAssets.search_icon).onPress(search!).paddingOnly(right: 24)
], ],
)), )),
@ -100,4 +105,42 @@ class CollapsingListView extends StatelessWidget {
), ),
); );
} }
Widget actionButton(BuildContext context, double t, {required String title, required String icon}) {
return AnimatedSize(
duration: Duration(milliseconds: 150),
child: Container(
height: 40,
padding: EdgeInsets.all(8),
margin: EdgeInsets.only(right: 24),
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.secondaryLightRedColor,
borderRadius: 12,
),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
spacing: 8.h,
children: [
Utils.buildSvgWithAssets(icon: icon, iconColor: AppColors.primaryRedColor),
if (t == 1)
Text(
title,
style: context.dynamicTextStyle(
color: AppColors.primaryRedColor,
letterSpacing: -0.4,
fontSize: (14 - (2 * (1 - t))).fSize,
fontWeight: FontWeight.lerp(
FontWeight.w300,
FontWeight.w500,
t,
)!,
),
),
],
),
),
);
}
} }

@ -8,7 +8,6 @@ import 'package:hmg_patient_app_new/core/enums.dart';
import 'package:hmg_patient_app_new/features/lab/models/resp_models/patient_lab_orders_response_model.dart'; import 'package:hmg_patient_app_new/features/lab/models/resp_models/patient_lab_orders_response_model.dart';
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart'; import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
import 'package:hmg_patient_app_new/features/lab/lab_view_model.dart'; import 'package:hmg_patient_app_new/features/lab/lab_view_model.dart';
import 'package:hmg_patient_app_new/presentation/lab/lab_result_item_view.dart'; import 'package:hmg_patient_app_new/presentation/lab/lab_result_item_view.dart';
import 'package:hmg_patient_app_new/presentation/lab/search_lab_report.dart'; import 'package:hmg_patient_app_new/presentation/lab/search_lab_report.dart';
import 'package:hmg_patient_app_new/theme/colors.dart'; import 'package:hmg_patient_app_new/theme/colors.dart';

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