Compare commits

...

14 Commits

Author SHA1 Message Date
aamir-csol 47ce5022d3 family screen & widgets 1 month ago
aamir-csol 1b652f877d Merge branch 'master' into dev_aamir
# Conflicts:
#	lib/presentation/medical_file/medical_file_page.dart
#	lib/widgets/chip/app_custom_chip_widget.dart
1 month ago
Haroon6138 938d95cb06 Merge pull request 'feature/search_by_region' (#55) from feature/search_by_region into master
Reviewed-on: #55
1 month ago
Haroon6138 989ea9ab3a Merge pull request 'dev_sultan' (#56) from dev_sultan into master
Reviewed-on: #56
1 month ago
Sultan khan 12447cdafb no message 1 month ago
Sultan khan 32c7608c83 Merge branch 'master' of http://34.17.52.180/Haroon6138/HMG_Patient_App_New into dev_sultan 1 month ago
Sultan khan 6d85227f11 lab order by test 1 month ago
taha.alam 8621a525a2 Merge remote-tracking branch 'origin/master' into feature/search_by_region 1 month ago
taha.alam 7093a26cb8 selection region arabic handling 1 month ago
taha.alam 27a0632d6d directional padding and alignment 1 month ago
Sultan khan 3d1d78ba48 Merge branch 'master' of http://34.17.52.180/Haroon6138/HMG_Patient_App_New into dev_sultan 1 month ago
Sultan khan 8f8c4c7f65 Merge branch 'master' of http://34.17.52.180/Haroon6138/HMG_Patient_App_New into dev_sultan
# Conflicts:
#	lib/presentation/medical_file/medical_file_page.dart
1 month ago
Sultan khan 28eae0e68e Merge branch 'dev_aamir' of http://34.17.52.180/Haroon6138/HMG_Patient_App_New into dev_sultan 1 month ago
Sultan khan e7c62a3321 Merge branch 'master' of http://34.17.52.180/Haroon6138/HMG_Patient_App_New into dev_sultan 1 month ago

@ -126,7 +126,7 @@
"gregorianDate": "التاريخ الميلادي", "gregorianDate": "التاريخ الميلادي",
"verifyLoginWith": "يرجى اختيار واحدة من الخيارات التالية للتحقق", "verifyLoginWith": "يرجى اختيار واحدة من الخيارات التالية للتحقق",
"registerUser": "تسجيل", "registerUser": "تسجيل",
"verifyWithFingerprint": "بصمة الإصبع", "verifyWithFingerprint":"البيومترية",
"verifyWithFaceid": "معرف الوجه", "verifyWithFaceid": "معرف الوجه",
"verifyWithSms": "رسالة قصيرة", "verifyWithSms": "رسالة قصيرة",
"verifyWithWhatsapp": "واتساب", "verifyWithWhatsapp": "واتساب",
@ -849,6 +849,7 @@
"pleaseEnterEmail": "يرجى إدخال البريد الإلكتروني", "pleaseEnterEmail": "يرجى إدخال البريد الإلكتروني",
"pleaseEnterAValidEmailFormat": "يرجى إدخال تنسيق بريد إلكتروني صالح", "pleaseEnterAValidEmailFormat": "يرجى إدخال تنسيق بريد إلكتروني صالح",
"selectCountry": "اختر الدولة", "selectCountry": "اختر الدولة",
"forLoginVerification": "للتحقق من تسجيل الدخول" "forLoginVerification": "للتحقق من تسجيل الدخول",
"searchHospital": "بحث في المستشفى"
} }

@ -126,7 +126,7 @@
"gregorianDate": "Gregorian Date", "gregorianDate": "Gregorian Date",
"verifyLoginWith": "Please choose one of the following options to verify", "verifyLoginWith": "Please choose one of the following options to verify",
"registerUser": "Register", "registerUser": "Register",
"verifyWithFingerprint": "Fingerprint", "verifyWithFingerprint": "Biometric",
"verifyWithFaceid": "Face ID", "verifyWithFaceid": "Face ID",
"verifyWithSms": "SMS", "verifyWithSms": "SMS",
"verifyWithWhatsapp": "Whatsapp", "verifyWithWhatsapp": "Whatsapp",
@ -845,5 +845,6 @@
"pleaseEnterAValidEmailFormat": "Please enter a valid email format", "pleaseEnterAValidEmailFormat": "Please enter a valid email format",
"selectCountry": "Select Country", "selectCountry": "Select Country",
"forLoginVerification": "for login verification", "forLoginVerification": "for login verification",
"lastLoginBy": "Last login by" "lastLoginBy": "Last login by",
"searchHospital": "Search Hospital"
} }

@ -22,7 +22,7 @@ extension WidgetExtensions on Widget {
Widget paddingSymmetrical(double horizontal, double vertical) => Padding(padding: EdgeInsets.symmetric(horizontal: horizontal, vertical: vertical), child: this); Widget paddingSymmetrical(double horizontal, double vertical) => Padding(padding: EdgeInsets.symmetric(horizontal: horizontal, vertical: vertical), child: this);
Widget paddingOnly({double left = 0.0, double right = 0.0, double top = 0.0, double bottom = 0.0}) => Widget paddingOnly({double left = 0.0, double right = 0.0, double top = 0.0, double bottom = 0.0}) =>
Padding(padding: EdgeInsets.only(left: left, right: right, top: top, bottom: bottom), child: this); Padding(padding: EdgeInsetsDirectional.only(start: left, end: right, top: top, bottom: bottom), child: this);
Widget toExpanded({int flex = 1}) => Expanded(flex: flex, child: this); Widget toExpanded({int flex = 1}) => Expanded(flex: flex, child: this);

@ -3,6 +3,7 @@ import 'dart:async';
import 'package:dartz/dartz.dart'; import 'package:dartz/dartz.dart';
import 'package:hmg_patient_app_new/core/api/api_client.dart'; import 'package:hmg_patient_app_new/core/api/api_client.dart';
import 'package:hmg_patient_app_new/core/api_consts.dart'; import 'package:hmg_patient_app_new/core/api_consts.dart';
import 'package:hmg_patient_app_new/core/app_state.dart';
import 'package:hmg_patient_app_new/core/common_models/generic_api_model.dart'; import 'package:hmg_patient_app_new/core/common_models/generic_api_model.dart';
import 'package:hmg_patient_app_new/core/common_models/privilege/PrivilegeModel.dart'; import 'package:hmg_patient_app_new/core/common_models/privilege/PrivilegeModel.dart';
import 'package:hmg_patient_app_new/core/exceptions/api_failure.dart'; import 'package:hmg_patient_app_new/core/exceptions/api_failure.dart';
@ -19,7 +20,8 @@ abstract class AuthenticationRepo {
Future<Either<Failure, GenericApiModel<dynamic>>> sendActivationCodeRepo({required dynamic sendActivationCodeReq, String? languageID, bool isRegister = false, bool isFormFamilyFile = false}); Future<Either<Failure, GenericApiModel<dynamic>>> sendActivationCodeRepo({required dynamic sendActivationCodeReq, String? languageID, bool isRegister = false, bool isFormFamilyFile = false});
Future<Either<Failure, GenericApiModel<dynamic>>> checkActivationCodeRepo({required dynamic newRequest, required String? activationCode, required bool isRegister, bool isExcludedUser = false}); Future<Either<Failure, GenericApiModel<dynamic>>> checkActivationCodeRepo(
{required dynamic newRequest, required String? activationCode, required bool isRegister, bool isFormFamilyFile = false, int? patientShareRequestID, int? responseID});
Future<Either<Failure, GenericApiModel<dynamic>>> checkIfUserAgreed({required dynamic commonAuthanticatedRequest}); Future<Either<Failure, GenericApiModel<dynamic>>> checkIfUserAgreed({required dynamic commonAuthanticatedRequest});
@ -178,7 +180,9 @@ class AuthenticationRepoImp implements AuthenticationRepo {
required dynamic newRequest, // could be CheckActivationCodeReq or CheckActivationCodeRegisterReq required dynamic newRequest, // could be CheckActivationCodeReq or CheckActivationCodeRegisterReq
required String? activationCode, required String? activationCode,
required bool isRegister, required bool isRegister,
bool isExcludedUser = false, bool isFormFamilyFile = false,
int? patientShareRequestID,
int? responseID,
}) async { }) async {
if (isRegister) { if (isRegister) {
newRequest["activationCode"] = activationCode ?? "0000"; newRequest["activationCode"] = activationCode ?? "0000";
@ -191,8 +195,16 @@ class AuthenticationRepoImp implements AuthenticationRepo {
newRequest.forRegisteration = newRequest.isRegister ?? false; newRequest.forRegisteration = newRequest.isRegister ?? false;
newRequest.isRegister = false; newRequest.isRegister = false;
} }
Map<String, dynamic> familyRequest = {};
if (isFormFamilyFile) {
familyRequest = newRequest.toJson();
familyRequest['PatientShareRequestID'] = patientShareRequestID;
familyRequest['ResponseID'] = responseID;
familyRequest['Status'] = 3;
familyRequest["PatientID"] = newRequest["PatientID"];
}
final endpoint = isExcludedUser final endpoint = isFormFamilyFile
? ApiConsts.checkActivationCodeForFamily ? ApiConsts.checkActivationCodeForFamily
: isRegister : isRegister
? ApiConsts.checkActivationCodeRegister ? ApiConsts.checkActivationCodeRegister
@ -204,7 +216,11 @@ class AuthenticationRepoImp implements AuthenticationRepo {
await apiClient.post( await apiClient.post(
endpoint, endpoint,
body: isRegister ? newRequest : newRequest.toJson(), body: isFormFamilyFile
? familyRequest
: isRegister
? newRequest
: newRequest.toJson(),
onFailure: (error, statusCode, {messageStatus, failureType}) { onFailure: (error, statusCode, {messageStatus, failureType}) {
failure = failureType; failure = failureType;
}, },

@ -382,12 +382,16 @@ class AuthenticationViewModel extends ChangeNotifier {
_appState.setUserRegistrationPayload = RegistrationDataModelPayload.fromJson(payload); _appState.setUserRegistrationPayload = RegistrationDataModelPayload.fromJson(payload);
} }
final resultEither = final resultEither = await _authenticationRepo.sendActivationCodeRepo(
await _authenticationRepo.sendActivationCodeRepo(sendActivationCodeReq: request, isRegister: checkIsUserComingForRegister(request: payload), languageID: 'er', isFormFamilyFile: isFormFamilyFile); sendActivationCodeReq: request, isRegister: checkIsUserComingForRegister(request: payload), languageID: 'er', isFormFamilyFile: isFormFamilyFile);
resultEither.fold( resultEither.fold(
(failure) async => await _errorHandlerService.handleError(failure: failure), (failure) async => await _errorHandlerService.handleError(failure: failure),
(apiResponse) async { (apiResponse) async {
int? patientShareRequestID = 0;
if (isFormFamilyFile) {
patientShareRequestID = apiResponse.data['PatientShareRequestID'];
}
if (apiResponse.messageStatus == 2) { if (apiResponse.messageStatus == 2) {
LoaderBottomSheet.hideLoader(); LoaderBottomSheet.hideLoader();
await _dialogService.showCommonBottomSheetWithoutH( await _dialogService.showCommonBottomSheetWithoutH(
@ -400,7 +404,15 @@ class AuthenticationViewModel extends ChangeNotifier {
LoaderBottomSheet.hideLoader(); LoaderBottomSheet.hideLoader();
if (!isComingFromResendOTP) { if (!isComingFromResendOTP) {
navigateToOTPScreen( navigateToOTPScreen(
otpTypeEnum: otpTypeEnum, phoneNumber: phoneNumber, isComingFromRegister: checkIsUserComingForRegister(request: payload), payload: payload, isExcludedUser: isExcludedUser); otpTypeEnum: otpTypeEnum,
phoneNumber: phoneNumber,
isComingFromRegister: checkIsUserComingForRegister(request: payload),
payload: payload,
isFormFamilyFile: isFormFamilyFile,
isExcludedUser: isExcludedUser,
responseID: responseID,
patientShareRequestID: patientShareRequestID,
);
} }
} else { } else {
// TODO: Handle isSMSSent false // TODO: Handle isSMSSent false
@ -424,8 +436,8 @@ class AuthenticationViewModel extends ChangeNotifier {
required OTPTypeEnum otpTypeEnum, required OTPTypeEnum otpTypeEnum,
required Function(String? message) onWrongActivationCode, required Function(String? message) onWrongActivationCode,
Function()? onResendActivation, Function()? onResendActivation,
bool isExcludedUser = false, bool isFormFamilyFile = false,
dynamic requestID, dynamic patientShareRequestID,
dynamic responseID}) async { dynamic responseID}) async {
bool isForRegister = (_appState.getUserRegistrationPayload.healthId != null || _appState.getUserRegistrationPayload.patientOutSa == true || _appState.getUserRegistrationPayload.patientOutSa == 1); bool isForRegister = (_appState.getUserRegistrationPayload.healthId != null || _appState.getUserRegistrationPayload.patientOutSa == true || _appState.getUserRegistrationPayload.patientOutSa == 1);
@ -453,12 +465,6 @@ class AuthenticationViewModel extends ChangeNotifier {
loginType: loginTypeEnum.toInt) loginType: loginTypeEnum.toInt)
.toJson(); .toJson();
if (isExcludedUser) {
request['PatientShareRequestID'] = requestID;
request['ResponseID'] = responseID;
request['Status'] = 3;
}
LoaderBottomSheet.showLoader(); LoaderBottomSheet.showLoader();
if (isForRegister) { if (isForRegister) {
if (_appState.getUserRegistrationPayload.patientOutSa == 0) request['DOB'] = _appState.getUserRegistrationPayload.dob; if (_appState.getUserRegistrationPayload.patientOutSa == 0) request['DOB'] = _appState.getUserRegistrationPayload.dob;
@ -468,7 +474,11 @@ class AuthenticationViewModel extends ChangeNotifier {
request["ForRegisteration"] = _appState.getUserRegistrationPayload.isRegister; request["ForRegisteration"] = _appState.getUserRegistrationPayload.isRegister;
request["isRegister"] = false; request["isRegister"] = false;
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(); LoaderBottomSheet.hideLoader();
@ -495,7 +505,12 @@ class AuthenticationViewModel extends ChangeNotifier {
}); });
} else { } else {
final resultEither = await _authenticationRepo.checkActivationCodeRepo( final resultEither = await _authenticationRepo.checkActivationCodeRepo(
newRequest: CheckActivationCodeRegisterReq.fromJson(request), activationCode: activationCode, isRegister: false, isExcludedUser: isExcludedUser); newRequest: CheckActivationCodeRegisterReq.fromJson(request),
activationCode: activationCode,
isRegister: false,
isFormFamilyFile: isFormFamilyFile,
patientShareRequestID: patientShareRequestID,
responseID: responseID);
resultEither.fold( resultEither.fold(
(failure) async => await _errorHandlerService.handleError( (failure) async => await _errorHandlerService.handleError(
@ -509,6 +524,8 @@ class AuthenticationViewModel extends ChangeNotifier {
LoaderBottomSheet.hideLoader(); LoaderBottomSheet.hideLoader();
await _dialogService.showCommonBottomSheetWithoutH(message: failure.message, label: LocaleKeys.notice.tr(), onOkPressed: () {}); await _dialogService.showCommonBottomSheetWithoutH(message: failure.message, label: LocaleKeys.notice.tr(), onOkPressed: () {});
}), (apiResponse) async { }), (apiResponse) async {
print("API Response Data: ${apiResponse.data}");
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') {
@ -605,14 +622,25 @@ class AuthenticationViewModel extends ChangeNotifier {
_navigationService.pushAndReplace(AppRoutes.landingScreen); _navigationService.pushAndReplace(AppRoutes.landingScreen);
} }
Future<void> navigateToOTPScreen({required OTPTypeEnum otpTypeEnum, required String phoneNumber, required bool isComingFromRegister, dynamic payload, bool isExcludedUser = false}) async { 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( _navigationService.pushToOtpScreen(
phoneNumber: phoneNumber, phoneNumber: phoneNumber,
isFormFamilyFile: isFormFamilyFile,
checkActivationCode: (int activationCode) async { checkActivationCode: (int activationCode) async {
await checkActivationCode( await checkActivationCode(
activationCode: activationCode.toString(), activationCode: activationCode.toString(),
isExcludedUser: isExcludedUser, isFormFamilyFile: isFormFamilyFile,
otpTypeEnum: otpTypeEnum, otpTypeEnum: otpTypeEnum,
responseID: responseID,
patientShareRequestID: patientShareRequestID,
onWrongActivationCode: (String? value) { onWrongActivationCode: (String? value) {
onWrongActivationCode(message: value); onWrongActivationCode(message: value);
}, },
@ -620,12 +648,16 @@ class AuthenticationViewModel extends ChangeNotifier {
}, },
onResendOTPPressed: (String phoneNumber) async { onResendOTPPressed: (String phoneNumber) async {
await sendActivationCode( await sendActivationCode(
otpTypeEnum: otpTypeEnum, otpTypeEnum: otpTypeEnum,
phoneNumber: phoneNumberController.text, phoneNumber: phoneNumberController.text,
nationalIdOrFileNumber: nationalIdController.text, nationalIdOrFileNumber: nationalIdController.text,
isForRegister: isComingFromRegister, isForRegister: isComingFromRegister,
isComingFromResendOTP: true, isComingFromResendOTP: true,
payload: payload); payload: payload,
isFormFamilyFile: isFormFamilyFile,
isExcludedUser: isExcludedUser,
responseID: responseID,
);
}, },
); );
} }

@ -428,13 +428,9 @@ class OTPVerificationScreen extends StatefulWidget {
final String phoneNumber; final String phoneNumber;
final Function(int code) checkActivationCode; final Function(int code) checkActivationCode;
final Function(String phoneNumber) onResendOTPPressed; final Function(String phoneNumber) onResendOTPPressed;
final bool isFormFamilyFile;
const OTPVerificationScreen({ const OTPVerificationScreen({super.key, required this.phoneNumber, required this.checkActivationCode, required this.onResendOTPPressed, required this.isFormFamilyFile});
super.key,
required this.phoneNumber,
required this.checkActivationCode,
required this.onResendOTPPressed,
});
@override @override
State<OTPVerificationScreen> createState() => _OTPVerificationScreenState(); State<OTPVerificationScreen> createState() => _OTPVerificationScreenState();
@ -559,7 +555,7 @@ class _OTPVerificationScreenState extends State<OTPVerificationScreen> {
LocaleKeys.weHaveSendOTP.tr().toText15(color: AppColors.inputLabelTextColor, letterSpacing: -0.4), LocaleKeys.weHaveSendOTP.tr().toText15(color: AppColors.inputLabelTextColor, letterSpacing: -0.4),
_getMaskedPhoneNumber().toText15(color: AppColors.inputLabelTextColor, isBold: true), _getMaskedPhoneNumber().toText15(color: AppColors.inputLabelTextColor, isBold: true),
LocaleKeys.via.tr().toText15(color: AppColors.inputLabelTextColor, letterSpacing: -0.4), LocaleKeys.via.tr().toText15(color: AppColors.inputLabelTextColor, letterSpacing: -0.4),
authVM.loginTypeEnum.displayName.toText15(color: AppColors.inputLabelTextColor, isBold: true, letterSpacing: -0.4), (widget.isFormFamilyFile ? LoginTypeEnum.sms.displayName : authVM.loginTypeEnum.displayName).toText15(color: AppColors.inputLabelTextColor, isBold: true, letterSpacing: -0.4),
appState.getUserRegistrationPayload.isRegister != null && appState.getUserRegistrationPayload.isRegister == true appState.getUserRegistrationPayload.isRegister != null && appState.getUserRegistrationPayload.isRegister == true
? LocaleKeys.forRegistrationVerification.tr().toText15(color: AppColors.inputLabelTextColor, letterSpacing: -0.4) ? LocaleKeys.forRegistrationVerification.tr().toText15(color: AppColors.inputLabelTextColor, letterSpacing: -0.4)
: LocaleKeys.forLoginVerification.tr().toText15(color: AppColors.inputLabelTextColor, letterSpacing: -0.4), : LocaleKeys.forLoginVerification.tr().toText15(color: AppColors.inputLabelTextColor, letterSpacing: -0.4),

@ -414,11 +414,6 @@ class BookAppointmentsViewModel extends ChangeNotifier {
} }
Future<void> getRegionMappedProjectList() async { Future<void> getRegionMappedProjectList() async {
//todo handle the case in the location is switch on
// if(hospitalList != null && hospitalList!.registeredDoctorMap != null && hospitalList!.registeredDoctorMap!.isNotEmpty){
// filteredHospitalList = hospitalList;
// return;
// }
isRegionListLoading = true; isRegionListLoading = true;
notifyListeners(); notifyListeners();
final result = await bookAppointmentsRepo.getProjectList(); final result = await bookAppointmentsRepo.getProjectList();
@ -432,7 +427,7 @@ class BookAppointmentsViewModel extends ChangeNotifier {
} else if (apiResponse.messageStatus == 1) { } else if (apiResponse.messageStatus == 1) {
var projectList = apiResponse.data!; var projectList = apiResponse.data!;
hospitalList = await DoctorMapper.getMappedHospitals(projectList, hospitalList = await DoctorMapper.getMappedHospitals(projectList,
isArabic: false, isArabic: _appState.isArabic(),
lat: _appState.userLat, lat: _appState.userLat,
lng: _appState.userLong, lng: _appState.userLong,
); );

@ -17,6 +17,8 @@ class LabViewModel extends ChangeNotifier {
List<String> get labSuggestions => _labSuggestionsList; List<String> get labSuggestions => _labSuggestionsList;
Set<TestDetails> uniqueTests = {};
LabViewModel({required this.labRepo, required this.errorHandlerService}); LabViewModel({required this.labRepo, required this.errorHandlerService});
initLabProvider() { initLabProvider() {
@ -32,8 +34,8 @@ class LabViewModel extends ChangeNotifier {
final result = await labRepo.getPatientLabOrders(); final result = await labRepo.getPatientLabOrders();
result.fold( result.fold(
(failure) async => await errorHandlerService.handleError(failure: failure), (failure) async => await errorHandlerService.handleError(failure: failure),
(apiResponse) { (apiResponse) {
if (apiResponse.messageStatus == 2) { if (apiResponse.messageStatus == 2) {
// dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {}); // dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {});
} else if (apiResponse.messageStatus == 1) { } else if (apiResponse.messageStatus == 1) {
@ -43,6 +45,7 @@ class LabViewModel extends ChangeNotifier {
isLabOrdersLoading = false; isLabOrdersLoading = false;
isLabResultsLoading = false; isLabResultsLoading = false;
filterSuggestions(); filterSuggestions();
getUniqueTestDescription();
notifyListeners(); notifyListeners();
if (onSuccess != null) { if (onSuccess != null) {
onSuccess(apiResponse); onSuccess(apiResponse);
@ -75,4 +78,15 @@ class LabViewModel extends ChangeNotifier {
} }
notifyListeners(); notifyListeners();
} }
getUniqueTestDescription() {
uniqueTests = {
for (var item in patientLabOrders)
if (item.testDetails != null)
...?item.testDetails?.map<TestDetails>((test) =>
TestDetails(description: test.description.toString(), testCode: test.testCode.toString(), testID: test.testID, createdOn: item.createdOn))
};
uniqueTests.forEach(print);
}
} }

@ -226,13 +226,14 @@ class TestDetails {
String? description; String? description;
String? testCode; String? testCode;
String? testID; String? testID;
String? createdOn;
TestDetails({this.description, this.testCode, this.testID}); TestDetails({this.description, this.testCode, this.testID, this.createdOn});
TestDetails.fromJson(Map<String, dynamic> json) { TestDetails.fromJson(Map<String, dynamic> json) {
description = json['Description']; description = json['Description'];
testCode = json['TestCode']; testCode = json['TestCode'];
testID = json['TestID']; testID = json['TestID'];
createdOn = json['CreatedOn'];
} }
Map<String, dynamic> toJson() { Map<String, dynamic> toJson() {
@ -240,6 +241,7 @@ class TestDetails {
data['Description'] = this.description; data['Description'] = this.description;
data['TestCode'] = this.testCode; data['TestCode'] = this.testCode;
data['TestID'] = this.testID; data['TestID'] = this.testID;
data['CreatedOn'] = this.createdOn;
return data; return data;
} }
} }

@ -17,6 +17,7 @@ import 'package:hmg_patient_app_new/features/medical_file/models/patient_vaccine
import 'package:hmg_patient_app_new/services/dialog_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/error_handler_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';
class MedicalFileViewModel extends ChangeNotifier { class MedicalFileViewModel extends ChangeNotifier {
int selectedTabIndex = 0; int selectedTabIndex = 0;
@ -301,6 +302,7 @@ class MedicalFileViewModel extends ChangeNotifier {
} }
Future<void> addFamilyFile({required OTPTypeEnum otpTypeEnum, required bool isExcludedUser}) async { Future<void> addFamilyFile({required OTPTypeEnum otpTypeEnum, required bool isExcludedUser}) async {
LoaderBottomSheet.showLoader();
AuthenticationViewModel authVM = getIt.get<AuthenticationViewModel>(); AuthenticationViewModel authVM = getIt.get<AuthenticationViewModel>();
NavigationService navigationService = getIt.get<NavigationService>(); NavigationService navigationService = getIt.get<NavigationService>();
FamilyFileRequest request = FamilyFileRequest request =
@ -311,9 +313,11 @@ class MedicalFileViewModel extends ChangeNotifier {
if (apiResponse != null && apiResponse.data != null) { if (apiResponse != null && apiResponse.data != null) {
request.isPatientExcluded = apiResponse.data["IsPatientExcluded"]; request.isPatientExcluded = apiResponse.data["IsPatientExcluded"];
request.responseID = apiResponse.data["ReponseID"]; request.responseID = apiResponse.data["ReponseID"];
LoaderBottomSheet.hideLoader();
_dialogService.showExceptionBottomSheet( _dialogService.showExceptionBottomSheet(
message: apiResponse.data['Message'], message: apiResponse.data['Message'],
onOkPressed: () { onOkPressed: () {
LoaderBottomSheet.showLoader();
print("=================== On Press Ok =================="); print("=================== On Press Ok ==================");
authVM.sendActivationCode( authVM.sendActivationCode(
otpTypeEnum: otpTypeEnum, otpTypeEnum: otpTypeEnum,
@ -324,7 +328,6 @@ class MedicalFileViewModel extends ChangeNotifier {
responseID: apiResponse.data["ReponseID"], responseID: apiResponse.data["ReponseID"],
isFormFamilyFile: true); isFormFamilyFile: true);
// insertFamilyData(payload: apiResponse.data![0]['ShareFamilyFileObj'], isExcludedPatient: apiResponse.data![0]['ShareFamilyFileObj']['IsPatientExcluded']);
}, },
onCancelPressed: () { onCancelPressed: () {
navigationService.pop(); navigationService.pop();

@ -1,4 +1,5 @@
import 'package:flutter/foundation.dart' show ChangeNotifier; import 'package:flutter/foundation.dart' show ChangeNotifier;
import 'package:hmg_patient_app_new/core/app_state.dart' show AppState;
import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/doctor_list_api_response.dart'; import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/doctor_list_api_response.dart';
import 'package:hmg_patient_app_new/presentation/book_appointment/select_clinic_page.dart'; import 'package:hmg_patient_app_new/presentation/book_appointment/select_clinic_page.dart';
import 'package:hmg_patient_app_new/services/navigation_service.dart'; import 'package:hmg_patient_app_new/services/navigation_service.dart';
@ -20,8 +21,9 @@ class AppointmentViaRegionViewmodel extends ChangeNotifier {
final NavigationService navigationService; final NavigationService navigationService;
AppointmentViaRegionState bottomSheetState = AppointmentViaRegionState bottomSheetState =
AppointmentViaRegionState.REGION_SELECTION; AppointmentViaRegionState.REGION_SELECTION;
final AppState appState;
AppointmentViaRegionViewmodel({required this.navigationService}); AppointmentViaRegionViewmodel({required this.navigationService,required this.appState});
void setSelectedRegionId(String? regionId) { void setSelectedRegionId(String? regionId) {
selectedRegionId = regionId; selectedRegionId = regionId;
@ -69,4 +71,6 @@ class AppointmentViaRegionViewmodel extends ChangeNotifier {
void setHospitalModel(PatientDoctorAppointmentList? hospital) { void setHospitalModel(PatientDoctorAppointmentList? hospital) {
selectedHospital = hospital; selectedHospital = hospital;
} }
bool get isArabic => appState.isArabic();
} }

@ -848,5 +848,6 @@ abstract class LocaleKeys {
static const pleaseEnterAValidEmailFormat = 'pleaseEnterAValidEmailFormat'; static const pleaseEnterAValidEmailFormat = 'pleaseEnterAValidEmailFormat';
static const selectCountry = 'selectCountry'; static const selectCountry = 'selectCountry';
static const forLoginVerification = 'forLoginVerification'; static const forLoginVerification = 'forLoginVerification';
static const searchHospital = 'searchHospital';
} }

@ -147,8 +147,8 @@ void main() async {
), ),
), ),
ChangeNotifierProvider<AppointmentViaRegionViewmodel>( ChangeNotifierProvider<AppointmentViaRegionViewmodel>(
create: (_) => create: (_) => AppointmentViaRegionViewmodel(
AppointmentViaRegionViewmodel(navigationService: getIt())) navigationService: getIt(), appState: getIt()))
], child: MyApp()), ], child: MyApp()),
), ),
); );

@ -38,7 +38,7 @@ class FacilityTypeSelectionWidget extends StatelessWidget {
), ),
), ),
Text( Text(
LocaleKeys.selectFacilitiesSubTitle, LocaleKeys.selectFacilitiesSubTitle.tr(),
style: TextStyle( style: TextStyle(
fontSize: 16, fontSize: 16,
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
@ -55,9 +55,11 @@ class FacilityTypeSelectionWidget extends StatelessWidget {
}), }),
).onPress( ).onPress(
() { () {
regionalViewModel.setFacility(FacilitySelection.HMG.name); if(bookAppointmentViewModel.hospitalList?.registeredDoctorMap?[selectedRegion]?.hmgSize != 0) {
regionalViewModel.setBottomSheetState( regionalViewModel.setFacility(FacilitySelection.HMG.name);
AppointmentViaRegionState.HOSPITAL_SELECTION); regionalViewModel.setBottomSheetState(
AppointmentViaRegionState.HOSPITAL_SELECTION);
}
}, },
), ),
SizedBox(height: 16.h), SizedBox(height: 16.h),
@ -69,9 +71,11 @@ class FacilityTypeSelectionWidget extends StatelessWidget {
"${bookAppointmentViewModel.hospitalList?.registeredDoctorMap?[selectedRegion]?.hmcSize ?? 0}" "${bookAppointmentViewModel.hospitalList?.registeredDoctorMap?[selectedRegion]?.hmcSize ?? 0}"
})).onPress( })).onPress(
() { () {
regionalViewModel.setFacility(FacilitySelection.HMC.name); if(bookAppointmentViewModel.hospitalList?.registeredDoctorMap?[selectedRegion]?.hmcSize!= 0 ) {
regionalViewModel.setBottomSheetState( regionalViewModel.setFacility(FacilitySelection.HMC.name);
AppointmentViaRegionState.HOSPITAL_SELECTION); regionalViewModel.setBottomSheetState(
AppointmentViaRegionState.HOSPITAL_SELECTION);
}
}, },
), ),
], ],

@ -50,7 +50,7 @@ class HospitalBottomSheetBody extends StatelessWidget {
SizedBox(height: 16.h), SizedBox(height: 16.h),
TextInputWidget( TextInputWidget(
labelText: LocaleKeys.search.tr(), labelText: LocaleKeys.search.tr(),
hintText: "Search Hospital".tr(), hintText: LocaleKeys.searchHospital.tr(),
controller: searchText, controller: searchText,
onChange: (value) { onChange: (value) {
appointmentsViewModel.filterHospitalListByString(value, regionalViewModel.selectedRegionId , regionalViewModel.selectedFacilityType == appointmentsViewModel.filterHospitalListByString(value, regionalViewModel.selectedRegionId , regionalViewModel.selectedFacilityType ==

@ -77,7 +77,7 @@ class RegionListItem extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Align( Align(
alignment: Alignment.centerLeft, alignment: AlignmentDirectional.centerStart,
child: Text( child: Text(
title, title,
style: TextStyle( style: TextStyle(

@ -200,7 +200,11 @@ class _BookAppointmentPageState extends State<BookAppointmentPage> {
void openRegionListBottomSheet(BuildContext context) { void openRegionListBottomSheet(BuildContext context) {
regionalViewModel.flush(); regionalViewModel.flush();
// AppointmentViaRegionViewmodel? viewmodel = null; // AppointmentViaRegionViewmodel? viewmodel = null;
showCommonBottomSheetWithoutHeight(context, title: "", titleWidget: Consumer<AppointmentViaRegionViewmodel>(builder: (_, data, __) => getTitle(data)), isDismissible: false, showCommonBottomSheetWithoutHeight(context,
title: "",
titleWidget: Consumer<AppointmentViaRegionViewmodel>(
builder: (_, data, __) => getTitle(data)),
isDismissible: false,
child: Consumer<AppointmentViaRegionViewmodel>(builder: (_, data, __) { child: Consumer<AppointmentViaRegionViewmodel>(builder: (_, data, __) {
return getRegionalSelectionWidget(data); return getRegionalSelectionWidget(data);
}), callBackFunc: () {}); }), callBackFunc: () {});
@ -234,9 +238,19 @@ class _BookAppointmentPageState extends State<BookAppointmentPage> {
if (data.selectedRegionId == null) { if (data.selectedRegionId == null) {
return LocaleKeys.selectRegion.tr().toText20(weight: FontWeight.w600); return LocaleKeys.selectRegion.tr().toText20(weight: FontWeight.w600);
} else { } else {
return Utils.buildSvgWithAssets(icon: AppAssets.arrow_back, iconColor: Color(0xff2B353E)).onPress(() { return
data.handleBackPress(); Transform.flip(
}); flipX: data.isArabic ? true : false,
child: Utils.buildSvgWithAssets(
icon: AppAssets.arrow_back,
iconColor: Color(0xff2B353E),
fit: BoxFit.contain,
),
).onPress(() {
data.handleBackPress();
});
} }
} }
} }

@ -0,0 +1,84 @@
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.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/enums.dart';
import 'package:hmg_patient_app_new/core/utils/date_util.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/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/theme/colors.dart';
import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart';
import 'package:hmg_patient_app_new/widgets/chip/app_custom_chip_widget.dart';
import 'package:hmg_patient_app_new/widgets/chip/custom_chip_widget.dart';
class LabOrderByTest extends StatelessWidget {
final VoidCallback onTap;
final int index;
final TestDetails? tests;
final bool isLoading;
final bool isExpanded;
const LabOrderByTest({super.key, required this.onTap, this.tests, required this.index, this.isLoading = false, this.isExpanded = false});
@override
build(BuildContext context) {
return AnimatedContainer(
duration: Duration(milliseconds: 300),
curve: Curves.easeInOut,
margin: EdgeInsets.symmetric(vertical: 8.h),
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 20.h, hasShadow: true),
child: InkWell(
onTap: () {
if (!isLoading) {
onTap();
}
},
child: Container(
key: ValueKey<int>(index),
padding: EdgeInsets.symmetric(horizontal: 16.h, vertical: 8.h),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// ...labOrder!.testDetails!.map((detail) {
Padding(
padding: EdgeInsets.only(bottom: 8.h),
child: '${tests!.description}'.toText14(weight: FontWeight.w500),
),
SizedBox(height: 12.h),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
AppCustomChipWidget(
richText: '${"Last Tested:".needTranslation} ${ DateUtil.formatDateToDate(DateUtil.convertStringToDate(tests!.createdOn), false)}'.toText12(isBold: true),
// chipType: ChipTypeEnum.lightBg,
backgroundColor: AppColors.greyLightColor,
textColor: AppColors.textColor,
// borderRadius: 5,
),
CustomButton(
icon: AppAssets.view_report_icon,
iconColor: AppColors.primaryRedColor,
iconSize: 16.h,
text: LocaleKeys.viewReport.tr(context: context),
onPressed: () {},
backgroundColor: AppColors.secondaryLightRedColor,
borderColor: AppColors.secondaryLightRedColor,
textColor: AppColors.primaryRedColor,
fontSize: 14,
fontWeight: FontWeight.bold,
borderRadius: 12,
padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
height: 40.h,
),
],
),
],
),
)));
}
}

@ -11,6 +11,7 @@ import 'package:hmg_patient_app_new/extensions/widget_extensions.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_order_by_test.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';
@ -32,7 +33,7 @@ class _LabOrdersPageState extends State<LabOrdersPage> {
List<List<TestDetails>?> labSuggestions = []; List<List<TestDetails>?> labSuggestions = [];
int? expandedIndex; int? expandedIndex;
String? selectedFilterText = ''; String? selectedFilterText = '';
int activeIndex = 0;
@override @override
void initState() { void initState() {
scheduleMicrotask(() { scheduleMicrotask(() {
@ -78,7 +79,10 @@ class _LabOrdersPageState extends State<LabOrdersPage> {
// CustomTabBarModel(null, "Completed".needTranslation), // CustomTabBarModel(null, "Completed".needTranslation),
], ],
onTabChange: (index) { onTabChange: (index) {
// myAppointmentsViewModel.onTabChange(index); activeIndex = index;
setState(() {
});
}, },
), ),
SizedBox(height: 16.h), SizedBox(height: 16.h),
@ -89,39 +93,73 @@ class _LabOrdersPageState extends State<LabOrdersPage> {
isSelected: true, isSelected: true,
) )
: SizedBox(), : SizedBox(),
ListView.builder( activeIndex == 0
shrinkWrap: true, ? ListView.builder(
physics: NeverScrollableScrollPhysics(), shrinkWrap: true,
padding: EdgeInsets.zero, physics: NeverScrollableScrollPhysics(),
itemCount: model.isLabOrdersLoading ? 5 : model.patientLabOrders.length, padding: EdgeInsets.zero,
itemBuilder: (context, index) { itemCount: model.isLabOrdersLoading ? 5 : model.patientLabOrders.length,
final isExpanded = expandedIndex == index; itemBuilder: (context, index) {
return model.isLabOrdersLoading final isExpanded = expandedIndex == index;
? LabResultItemView( return model.isLabOrdersLoading
? LabResultItemView(
onTap: () {},
labOrder: null,
index: index,
isLoading: true,
)
: AnimationConfiguration.staggeredList(
position: index,
duration: const Duration(milliseconds: 500),
child: SlideAnimation(
verticalOffset: 100.0,
child: FadeInAnimation(
child: LabResultItemView(
onTap: () {
setState(() {
expandedIndex = isExpanded ? null : index;
});
},
labOrder: model.patientLabOrders[index],
index: index,
isExpanded: isExpanded)),
),
);
},
)
: ListView.builder(
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
padding: EdgeInsets.zero,
itemCount: model.isLabOrdersLoading ? 5 :model.uniqueTests.toList().length,
itemBuilder: (context, index) {
final isExpanded = expandedIndex == index;
return model.isLabOrdersLoading
? LabResultItemView(
onTap: () {}, onTap: () {},
labOrder: null, labOrder: null,
index: index, index: index,
isLoading: true, isLoading: true,
) ) : AnimationConfiguration.staggeredList(
: AnimationConfiguration.staggeredList( position: index,
position: index, duration: const Duration(milliseconds: 500),
duration: const Duration(milliseconds: 500), child: SlideAnimation(
child: SlideAnimation( verticalOffset: 100.0,
verticalOffset: 100.0, child: FadeInAnimation(
child: FadeInAnimation( child: LabOrderByTest(
child: LabResultItemView( onTap: () {
onTap: () { setState(() {
setState(() { expandedIndex = isExpanded ? null : index;
expandedIndex = isExpanded ? null : index; });
}); },
}, tests: model.uniqueTests.toList()[index],
labOrder: model.patientLabOrders[index], index: index,
index: index, isExpanded: isExpanded)),
isExpanded: isExpanded)), ),
), );
);
}, },
), )
], ],
); );
}, },

@ -776,4 +776,9 @@ class _MedicalFilePageState extends State<MedicalFilePage> {
return Container(); return Container();
} }
} }
getMember() {
// AuthanticationViewModel authanticationViewModel = getIt.get<AuthanticationViewModel>();
// RequestUtils.getAddFamilyRequest(nationalIDorFile: nationalIDorFile, mobileNo: mobileNo, countryCode: countryCode, loginType: loginType);
}
} }

@ -22,9 +22,9 @@ class NavigationService {
navigatorKey.currentState?.pushReplacementNamed(routeName); navigatorKey.currentState?.pushReplacementNamed(routeName);
} }
Future<T?> pushToOtpScreen<T>({required String phoneNumber, required Function(int code) checkActivationCode, required Function(String phoneNumber) onResendOTPPressed}) { Future<T?> pushToOtpScreen<T>({required String phoneNumber, required Function(int code) checkActivationCode, required Function(String phoneNumber) onResendOTPPressed, bool isFormFamilyFile = false}) {
return navigatorKey.currentState!.push( return navigatorKey.currentState!.push(
MaterialPageRoute(builder: (_) => OTPVerificationScreen(phoneNumber: phoneNumber, checkActivationCode: checkActivationCode, onResendOTPPressed: onResendOTPPressed)), MaterialPageRoute(builder: (_) => OTPVerificationScreen(phoneNumber: phoneNumber, checkActivationCode: checkActivationCode, onResendOTPPressed: onResendOTPPressed, isFormFamilyFile : isFormFamilyFile)),
); );
} }

Loading…
Cancel
Save