diff --git a/assets/images/png/dummy_user.png b/assets/images/png/dummy_user.png
new file mode 100644
index 0000000..b4bace4
Binary files /dev/null and b/assets/images/png/dummy_user.png differ
diff --git a/assets/images/svg/active-check.svg b/assets/images/svg/active-check.svg
new file mode 100644
index 0000000..c94a3a0
--- /dev/null
+++ b/assets/images/svg/active-check.svg
@@ -0,0 +1,3 @@
+
diff --git a/assets/images/svg/alert-square.svg b/assets/images/svg/alert-square.svg
new file mode 100644
index 0000000..87b52e3
--- /dev/null
+++ b/assets/images/svg/alert-square.svg
@@ -0,0 +1,3 @@
+
diff --git a/assets/images/svg/arrow-right.svg b/assets/images/svg/arrow-right.svg
new file mode 100644
index 0000000..8818d72
--- /dev/null
+++ b/assets/images/svg/arrow-right.svg
@@ -0,0 +1,3 @@
+
diff --git a/assets/images/svg/delete_icon.svg b/assets/images/svg/delete_icon.svg
new file mode 100644
index 0000000..2e37d0d
--- /dev/null
+++ b/assets/images/svg/delete_icon.svg
@@ -0,0 +1,3 @@
+
diff --git a/assets/images/svg/switch_user.svg b/assets/images/svg/switch_user.svg
new file mode 100644
index 0000000..fa8e47e
--- /dev/null
+++ b/assets/images/svg/switch_user.svg
@@ -0,0 +1,8 @@
+
diff --git a/lib/core/api/api_client.dart b/lib/core/api/api_client.dart
index a36f554..24f682b 100644
--- a/lib/core/api/api_client.dart
+++ b/lib/core/api/api_client.dart
@@ -88,16 +88,16 @@ class ApiClientImp implements ApiClient {
@override
post(
- String endPoint, {
- required Map body,
- required Function(dynamic response, int statusCode, {int? messageStatus, String? errorMessage}) onSuccess,
- required Function(String error, int statusCode, {int? messageStatus, Failure? failureType}) onFailure,
- bool isAllowAny = false,
- bool isExternal = false,
- bool isRCService = false,
- bool isPaymentServices = false,
- bool bypassConnectionCheck = false,
- }) async {
+ String endPoint, {
+ required Map body,
+ required Function(dynamic response, int statusCode, {int? messageStatus, String? errorMessage}) onSuccess,
+ required Function(String error, int statusCode, {int? messageStatus, Failure? failureType}) onFailure,
+ bool isAllowAny = false,
+ bool isExternal = false,
+ bool isRCService = false,
+ bool isPaymentServices = false,
+ bool bypassConnectionCheck = false,
+ }) async {
String url;
if (isExternal) {
url = endPoint;
@@ -173,8 +173,8 @@ class ApiClientImp implements ApiClient {
body[_appState.isAuthenticated ? 'TokenID' : 'LogInTokenID'] = _appState.appAuthToken;
}
- body['TokenID'] = "@dm!n";
- body['PatientID'] = 4772172;
+ // body['TokenID'] = "@dm!n";
+ // body['PatientID'] = 4772172;
// body['PatientTypeID'] = 1;
//
// body['PatientOutSA'] = 0;
diff --git a/lib/core/api_consts.dart b/lib/core/api_consts.dart
index 98c7ec0..9591cfe 100644
--- a/lib/core/api_consts.dart
+++ b/lib/core/api_consts.dart
@@ -727,7 +727,7 @@ const FAMILY_FILES= 'Services/Authentication.svc/REST/GetAllSharedRecordsByStatu
class ApiConsts {
static const maxSmallScreen = 660;
- static AppEnvironmentTypeEnum appEnvironmentType = AppEnvironmentTypeEnum.uat;
+ static AppEnvironmentTypeEnum appEnvironmentType = AppEnvironmentTypeEnum.prod;
// static String baseUrl = 'https://uat.hmgwebservices.com/'; // HIS API URL UAT
@@ -832,6 +832,13 @@ class ApiConsts {
static final String registerUser = 'Services/Authentication.svc/REST/PatientRegistration';
static final String addFamilyFile = 'Services/Patients.svc/REST/ShareFamilyFileService';
+ static final String sendFamilyFileActivation = 'Services/Authentication.svc/REST/SendActivationCodeForFamilyFile';
+ static final String checkActivationCodeForFamily = 'Services/Authentication.svc/REST/CheckActivationCodeForFamilyFile';
+ static final String getAllPendingRecordsByResponseId = 'Services/Authentication.svc/REST/GetAllPendingRecordsByResponseId';
+ static final String getAllSharedRecordsByStatus = 'Services/Authentication.svc/REST/GetAllSharedRecordsByStatus';
+ static final String removeFileFromFamilyMembers = 'Services/Authentication.svc/REST/ActiveDeactive_PatientFile';
+ static final String acceptAndRejectFamilyFile = 'Services/Authentication.svc/REST/Update_FileStatus';
+
// static values for Api
static final double appVersionID = 18.7;
diff --git a/lib/core/app_assets.dart b/lib/core/app_assets.dart
index d1b8b93..1e9eaa4 100644
--- a/lib/core/app_assets.dart
+++ b/lib/core/app_assets.dart
@@ -152,6 +152,9 @@ class AppAssets {
static const String ic_filters = '$svgBasePath/filters.svg';
static const String ic_close = '$svgBasePath/ic_close.svg';
static const String ic_cross_circle = '$svgBasePath/cross_circle.svg';
+ static const String switch_user = '$svgBasePath/switch_user.svg';
+ static const String activeCheck = '$svgBasePath/active-check.svg';
+ static const String deleteIcon = '$svgBasePath/delete_icon.svg';
//bottom navigation//
static const String homeBottom = '$svgBasePath/home_bottom.svg';
@@ -163,6 +166,8 @@ class AppAssets {
static const String feedback = '$svgBasePath/feedback.svg';
static const String news = '$svgBasePath/news.svg';
static const String heart = '$svgBasePath/heart.svg';
+ static const String alertSquare = '$svgBasePath/alert-square.svg';
+ static const String arrowRight = '$svgBasePath/arrow-right.svg';
// PNGS //
static const String hmg_logo = '$pngBasePath/hmg_logo.png';
@@ -177,6 +182,7 @@ class AppAssets {
static const String tamara_en = '$pngBasePath/tamara_en.png';
static const String visa = '$pngBasePath/visa.png';
static const String lockIcon = '$pngBasePath/lock-icon.png';
+ static const String dummy_user = '$pngBasePath/dummy_user.png';
}
class AppAnimations {
diff --git a/lib/core/app_state.dart b/lib/core/app_state.dart
index c906374..404e22b 100644
--- a/lib/core/app_state.dart
+++ b/lib/core/app_state.dart
@@ -37,14 +37,16 @@ class AppState {
AuthenticatedUser? _authenticatedRootUser;
AuthenticatedUser? _authenticatedChildUser;
- void setAuthenticatedUser(AuthenticatedUser authenticatedUser, {bool isFamily = false}) {
+ int? _superUserID;
+ bool isChildLoggedIn = false;
+
+ void setAuthenticatedUser(AuthenticatedUser? authenticatedUser, {bool isFamily = false}) {
if (isFamily) {
_authenticatedChildUser = authenticatedUser;
} else {
setIsAuthenticated = true;
_authenticatedRootUser = authenticatedUser;
}
-
}
AuthenticatedUser? getAuthenticatedUser({bool isFamily = false}) {
@@ -55,6 +57,14 @@ class AppState {
}
}
+ int? get getSuperUserID => _superUserID;
+
+ bool get getIsChildLoggedIn => isChildLoggedIn;
+
+ set setSuperUserID(int? value) => _superUserID = value;
+
+ set setIsChildLoggedIn(bool value) => isChildLoggedIn = value;
+
String _userBloodGroup = "";
String get getUserBloodGroup => _userBloodGroup;
@@ -97,6 +107,14 @@ class AppState {
set setDeviceTypeID(v) => deviceTypeID = v;
+ String _familyFileTokenID = "";
+
+ String get getFamilyFileTokenID => _familyFileTokenID;
+
+ set setFamilyFileTokenID(String value) {
+ _familyFileTokenID = value;
+ }
+
List vidaPlusProjectList = [];
List privilegeModelList = [];
List hMCProjectListModel = [];
@@ -135,9 +153,8 @@ class AppState {
}
///this will be called if there is any problem in getting the user location
- void resetLocation(){
+ void resetLocation() {
userLong = 0.0;
userLong = 0.0;
}
-
}
diff --git a/lib/core/dependencies.dart b/lib/core/dependencies.dart
index 3ce8a19..42349ef 100644
--- a/lib/core/dependencies.dart
+++ b/lib/core/dependencies.dart
@@ -26,6 +26,7 @@ import 'package:hmg_patient_app_new/features/payfort/payfort_repo.dart';
import 'package:hmg_patient_app_new/features/payfort/payfort_view_model.dart';
import 'package:hmg_patient_app_new/features/prescriptions/prescriptions_repo.dart';
import 'package:hmg_patient_app_new/features/prescriptions/prescriptions_view_model.dart';
+import 'package:hmg_patient_app_new/features/profile_settings/profile_settings_view_model.dart';
import 'package:hmg_patient_app_new/features/radiology/radiology_repo.dart';
import 'package:hmg_patient_app_new/features/radiology/radiology_view_model.dart';
import 'package:hmg_patient_app_new/services/analytics/analytics_service.dart';
@@ -103,11 +104,7 @@ class AppDependencies {
// Global/shared VMs → LazySingleton
getIt.registerLazySingleton(
- () => LabViewModel(
- labRepo: getIt(),
- errorHandlerService: getIt(),
- navigationService: getIt()
- ),
+ () => LabViewModel(labRepo: getIt(), errorHandlerService: getIt(), navigationService: getIt()),
);
getIt.registerLazySingleton(
@@ -173,6 +170,7 @@ class AppDependencies {
() => AuthenticationViewModel(
authenticationRepo: getIt(), cacheService: getIt(), navigationService: getIt(), dialogService: getIt(), appState: getIt(), errorHandlerService: getIt(), localAuthService: getIt()),
);
+ getIt.registerLazySingleton(() => ProfileSettingsViewModel());
getIt.registerLazySingleton(
() => DateRangeSelectorRangeViewModel(),
diff --git a/lib/core/enums.dart b/lib/core/enums.dart
index bb6c6fe..4151bed 100644
--- a/lib/core/enums.dart
+++ b/lib/core/enums.dart
@@ -30,6 +30,8 @@ enum LoginTypeEnum { sms, whatsapp, face, fingerprint }
enum AppEnvironmentTypeEnum { dev, uat, preProd, qa, staging, prod }
+enum FamilyFileEnum { active, inactive, blocked, deleted, pending, rejected }
+
extension CalenderExtension on CalenderEnum {
int get toInt {
switch (this) {
@@ -138,6 +140,61 @@ extension OTPTypeEnumExtension on OTPTypeEnum {
}
}
+extension FamilyFileEnumExtenshion on FamilyFileEnum {
+ int get toInt {
+ switch (this) {
+ case FamilyFileEnum.active:
+ return 3;
+ case FamilyFileEnum.blocked:
+ return 1;
+ case FamilyFileEnum.deleted:
+ return 0;
+ case FamilyFileEnum.pending:
+ return 2;
+ case FamilyFileEnum.inactive:
+ return 6;
+ case FamilyFileEnum.rejected:
+ return 4;
+ }
+ }
+
+ String get displayName {
+ AppState appState = getIt.get();
+ bool isArabic = appState.getLanguageID() == 1 ? true : false;
+ switch (this) {
+ case FamilyFileEnum.active:
+ return isArabic ? 'نشط' : 'Active';
+ case FamilyFileEnum.inactive:
+ return isArabic ? 'غير نشط' : 'Inactive';
+ case FamilyFileEnum.blocked:
+ return isArabic ? 'محظور' : 'Blocked';
+ case FamilyFileEnum.deleted:
+ return isArabic ? 'محذوف' : 'Deleted';
+ case FamilyFileEnum.pending:
+ return isArabic ? 'قيد الانتظار' : 'Pending';
+ case FamilyFileEnum.rejected:
+ return isArabic ? 'مرفوض' : 'Rejected';
+ }
+ }
+
+ static FamilyFileEnum? fromValue(int value) {
+ switch (value) {
+ case 0:
+ return FamilyFileEnum.pending;
+ case 2:
+ return FamilyFileEnum.blocked;
+ case 1:
+ return FamilyFileEnum.deleted;
+ case 3:
+ return FamilyFileEnum.active;
+ case 4:
+ return FamilyFileEnum.inactive;
+ default:
+ return null;
+ }
+ }
+}
+
enum ServiceTypeEnum {
advancePayment, //3
ancillaryOrder, //3
diff --git a/lib/core/utils/request_utils.dart b/lib/core/utils/request_utils.dart
index 8b993f1..a4ea936 100644
--- a/lib/core/utils/request_utils.dart
+++ b/lib/core/utils/request_utils.dart
@@ -9,6 +9,7 @@ import 'package:hmg_patient_app_new/extensions/string_extensions.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/request_models/send_activation_request_model.dart';
import 'package:hmg_patient_app_new/features/common/models/commong_authanticated_req_model.dart';
+import 'package:hmg_patient_app_new/features/common/models/family_file_request.dart';
class RequestUtils {
static dynamic getPatientAuthenticationRequest({
@@ -125,6 +126,9 @@ class RequestUtils {
required bool isForRegister,
required bool isFileNo,
dynamic payload,
+ required bool isExcludedUser,
+ required bool isFormFamilyFile,
+ int? responseID,
}) {
AppState _appState = getIt.get();
var request = SendActivationRequest();
@@ -156,6 +160,15 @@ class RequestUtils {
request.isRegister = false;
}
request.deviceTypeID = request.searchType;
+
+ if (isFormFamilyFile) {
+ //INFO: Only for Excluded User Family Member Addition
+ request.isPatientExcluded = isExcludedUser;
+ request.responseID = responseID;
+ request.status = 2;
+ request.familyRegionID = zipCode == CountryEnum.saudiArabia.countryCode ? 1 : 2;
+ }
+
return request;
}
@@ -247,19 +260,29 @@ class RequestUtils {
};
}
- static dynamic getAddFamilyRequest({required String nationalIDorFile, required String mobileNo, required String countryCode, required int loginType}) {
- var request = {};
+ static Future getAddFamilyRequest({required String nationalIDorFile, required String mobileNo, required String countryCode}) async {
+ FamilyFileRequest request = FamilyFileRequest();
+ int? loginType = 0;
+
+ if (countryCode == CountryEnum.saudiArabia.countryCode || countryCode == '+966') {
+ loginType = (nationalIDorFile.length == 10) ? 1 : 2;
+ } else if (countryCode == CountryEnum.unitedArabEmirates.countryCode || countryCode == '+971') {
+ loginType = (nationalIDorFile.length == 15) ? 1 : 2;
+ }
+
if (loginType == 1) {
- request["sharedPatientID"] = 0;
- request["sharedPatientIdentificationID"] = nationalIDorFile;
+ request.sharedPatientId = 0;
+ request.sharedPatientIdentificationId = nationalIDorFile;
} else if (loginType == 2) {
- request["sharedPatientID"] = int.parse(nationalIDorFile);
- request["sharedPatientIdentificationID"] = '';
+ request.sharedPatientId = int.parse(nationalIDorFile);
+ request.sharedPatientIdentificationId = '';
}
- request["searchType"] = loginType;
- request["sharedPatientMobileNumber"] = mobileNo;
- request["zipCode"] = countryCode;
- request["isRegister"] = false;
- request["patientStatus"] = 2;
+ request.searchType = loginType;
+ request.sharedPatientMobileNumber = mobileNo;
+ request.zipCode = countryCode;
+ request.isRegister = false;
+ request.patientStatus = 2;
+ request.isDentalAllowedBackend = false;
+ return request;
}
}
diff --git a/lib/core/utils/utils.dart b/lib/core/utils/utils.dart
index c9eef9d..c4a2db8 100644
--- a/lib/core/utils/utils.dart
+++ b/lib/core/utils/utils.dart
@@ -629,8 +629,17 @@ class Utils {
double width = 24,
double height = 24,
BoxFit fit = BoxFit.cover,
+ double? border,
+ double? borderRadius,
}) {
- return Image.asset(icon, width: width, height: height, fit: fit);
+ return Container(
+ decoration: BoxDecoration(
+ border: border != null ? Border.all(color: AppColors.whiteColor, width: border) : null,
+ borderRadius: border != null ? BorderRadius.circular(borderRadius ?? 0) : null,
+ ),
+ child: Image.asset(icon, width: width, height: height, fit: fit),
+ );
+ // return Image.asset(icon, width: width, height: height, fit: fit, );
}
/// Widget to build an SVG from network
diff --git a/lib/extensions/string_extensions.dart b/lib/extensions/string_extensions.dart
index 059e553..4432737 100644
--- a/lib/extensions/string_extensions.dart
+++ b/lib/extensions/string_extensions.dart
@@ -1,4 +1,6 @@
import 'package:hmg_patient_app_new/core/app_assets.dart';
+import 'package:hmg_patient_app_new/core/app_state.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/size_utils.dart';
import 'package:auto_size_text/auto_size_text.dart';
@@ -365,7 +367,8 @@ extension DynamicTextStyleExtension on BuildContext {
TextBaseline? textBaseline,
FontStyle? fontStyle,
bool isLanguageSwitcher = false}) {
- final family = FontUtils.getFontFamilyForLanguage(false); // TODO: @Aamir make it dynamic based on app language
+ AppState appState = getIt.get();
+ final family = appState.getLanguageCode() == "ar" ? 'GESSTwo' : 'Poppins';
return TextStyle(
fontFamily: family,
fontSize: fontSize,
diff --git a/lib/features/authentication/authentication_repo.dart b/lib/features/authentication/authentication_repo.dart
index 2eaeb80..bec5470 100644
--- a/lib/features/authentication/authentication_repo.dart
+++ b/lib/features/authentication/authentication_repo.dart
@@ -3,8 +3,10 @@ import 'dart:async';
import 'package:dartz/dartz.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/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/privilege/PrivilegeModel.dart';
+import 'package:hmg_patient_app_new/core/dependencies.dart';
import 'package:hmg_patient_app_new/core/exceptions/api_failure.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/resp_models/select_device_by_imei.dart';
@@ -17,12 +19,18 @@ abstract class AuthenticationRepo {
Future>> checkPatientAuthentication({required dynamic checkPatientAuthenticationReq});
- Future>> sendActivationCodeRepo({required dynamic sendActivationCodeReq, String? languageID, bool isRegister = false});
+ Future>> sendActivationCodeRepo({required dynamic sendActivationCodeReq, String? languageID, bool isRegister = false, bool isFormFamilyFile = false});
Future>> checkActivationCodeRepo(
- {required dynamic newRequest, // could be CheckActivationCodeReq or CheckActivationCodeRegisterReq
+ {required dynamic newRequest,
required String? activationCode,
- required bool isRegister});
+ required bool isRegister,
+ bool isFormFamilyFile = false,
+ int? patientShareRequestID,
+ int? responseID,
+ bool isSwitchUser = false,
+ int? patientID,
+ int? loginType});
Future>> checkIfUserAgreed({required dynamic commonAuthanticatedRequest});
@@ -134,18 +142,33 @@ class AuthenticationRepoImp implements AuthenticationRepo {
required dynamic sendActivationCodeReq,
String? languageID,
bool isRegister = false,
+ bool isFormFamilyFile = false,
}) async {
int isOutKsa = (sendActivationCodeReq.zipCode == '966' || sendActivationCodeReq.zipCode == '+966') ? 0 : 1;
sendActivationCodeReq.patientOutSA = isOutKsa;
sendActivationCodeReq.isDentalAllowedBackend = false;
+ final payload = sendActivationCodeReq.toJson();
+ if (isFormFamilyFile) {
+ payload.remove("MobileNo");
+ payload.remove("NationalID");
+ payload.remove("SMSSignature");
+ payload.remove("ResponseID");
+ print("=================== Final Payload ===================");
+ print(payload);
+ print("=====================================================");
+ }
try {
GenericApiModel? apiResponse;
Failure? failure;
await apiClient.post(
- isRegister ? ApiConsts.sendActivationCodeRegister : ApiConsts.sendActivationCode,
- body: sendActivationCodeReq.toJson(),
+ isFormFamilyFile
+ ? ApiConsts.sendFamilyFileActivation
+ : isRegister
+ ? ApiConsts.sendActivationCodeRegister
+ : ApiConsts.sendActivationCode,
+ body: isFormFamilyFile ? payload : sendActivationCodeReq.toJson(),
onFailure: (error, statusCode, {messageStatus, failureType}) {
failure = failureType;
},
@@ -172,24 +195,122 @@ class AuthenticationRepoImp implements AuthenticationRepo {
}
@override
- Future>> checkActivationCodeRepo({
- required dynamic newRequest, // could be CheckActivationCodeReq or CheckActivationCodeRegisterReq
- required String? activationCode,
- required bool isRegister,
- }) async {
+ Future>> checkActivationCodeRepo(
+ {required dynamic newRequest, // could be CheckActivationCodeReq or CheckActivationCodeRegisterReq
+ required String? activationCode,
+ required bool isRegister,
+ bool isFormFamilyFile = false,
+ int? patientShareRequestID,
+ int? responseID,
+ bool isSwitchUser = false,
+ int? patientID,
+ int? loginType}) async {
+ AppState appState = getIt.get();
+ // if (isRegister) {
+ // newRequest["activationCode"] = activationCode ?? "0000";
+ // newRequest["isSilentLogin"] = activationCode != null ? false : true;
+ // } else {
+ // newRequest.activationCode = activationCode ?? "0000";
+ // newRequest.isSilentLogin = activationCode != null ? false : true;
+ // newRequest.projectOutSA = newRequest.zipCode == '966' ? false : true;
+ // newRequest.isDentalAllowedBackend = false;
+ // newRequest.forRegisteration = newRequest.isRegister ?? false;
+ // newRequest.isRegister = false;
+ // }
+ // Map familyRequest = {};
+ // if (isFormFamilyFile) {
+ // AppState appState = getIt.get();
+ // familyRequest = {};
+ // familyRequest['PatientShareRequestID'] = patientShareRequestID;
+ // familyRequest['ResponseID'] = responseID;
+ // familyRequest['Status'] = 3;
+ // familyRequest["PatientID"] = appState.getAuthenticatedUser()!.patientId ?? 0;
+ // familyRequest["LogInTokenID"] = appState.getFamilyFileTokenID;
+ // familyRequest["activationCode"] = activationCode ?? "0000";
+ // familyRequest["PatientMobileNumber"] = newRequest.patientMobileNumber;
+ // familyRequest["PatientIdentificationID"] = newRequest.patientIdentificationID;
+ // }
+ // Map switchRequest = {};
+ // if (isSwitchUser) {
+ // switchRequest = newRequest.toJson();
+ //
+ // switchRequest['PatientID'] = responseID;
+ // switchRequest['IsSilentLogin'] = true;
+ // switchRequest['LogInTokenID'] = null;
+ // switchRequest['SearchType'] = 2;
+ // if (loginType != 0) {
+ // switchRequest['SuperUser'] = patientID;
+ // switchRequest['DeviceToken'] = null;
+ // } else {
+ // switchRequest["LoginType"] = 2;
+ // }
+ //
+ // if (appState.getSuperUserID == responseID) {
+ // // switchRequest['LoginType'] = 3;
+ // switchRequest['PatientIdentificationID'] = "";
+ // // switchRequest['ProjectOutSA'] = newRequest.zipCode == '966' ? false : true;
+ // switchRequest.remove('NationalID');
+ // switchRequest.remove('isDentalAllowedBackend');
+ // switchRequest.remove('ProjectOutSA');
+ // switchRequest.remove('ForRegisteration');
+ // appState.setSuperUserID = null;
+ // }
+ // }
+
if (isRegister) {
newRequest["activationCode"] = activationCode ?? "0000";
- newRequest["isSilentLogin"] = activationCode != null ? false : true;
+ newRequest["isSilentLogin"] = activationCode == null;
} else {
newRequest.activationCode = activationCode ?? "0000";
- newRequest.isSilentLogin = activationCode != null ? false : true;
- newRequest.projectOutSA = newRequest.zipCode == '966' ? false : true;
+ newRequest.isSilentLogin = activationCode == null;
+ newRequest.projectOutSA = newRequest.zipCode != '966';
newRequest.isDentalAllowedBackend = false;
newRequest.forRegisteration = newRequest.isRegister ?? false;
newRequest.isRegister = false;
}
- final endpoint = isRegister ? ApiConsts.checkActivationCodeRegister : ApiConsts.checkActivationCode;
+ Map familyRequest = {};
+ if (isFormFamilyFile) {
+ familyRequest = {
+ 'PatientShareRequestID': patientShareRequestID,
+ 'ResponseID': responseID,
+ 'Status': 3,
+ // 'PatientID': appState.getAuthenticatedUser()?.patientId ?? 0,
+ 'LogInTokenID': appState.getFamilyFileTokenID,
+ 'activationCode': activationCode ?? "0000",
+ 'PatientMobileNumber': newRequest.patientMobileNumber,
+ 'PatientIdentificationID': newRequest.patientIdentificationID,
+ };
+ }
+
+ Map switchRequest = {};
+ if (isSwitchUser) {
+ switchRequest = newRequest.toJson();
+ switchRequest.addAll({
+ 'PatientID': responseID,
+ 'IsSilentLogin': true,
+ 'LogInTokenID': null,
+ 'SearchType': 2,
+ });
+
+ if (loginType != 0) {
+ switchRequest['SuperUser'] = patientID;
+ switchRequest['DeviceToken'] = null;
+ } else {
+ switchRequest['LoginType'] = 2;
+ }
+
+ if (appState.getSuperUserID == responseID) {
+ switchRequest['PatientIdentificationID'] = "";
+ switchRequest.removeWhere((key, value) => ['NationalID', 'isDentalAllowedBackend', 'ProjectOutSA', 'ForRegisteration'].contains(key));
+ }
+ }
+
+ final endpoint = isFormFamilyFile
+ ? ApiConsts.checkActivationCodeForFamily
+ : isRegister
+ ? ApiConsts.checkActivationCodeRegister
+ : ApiConsts.checkActivationCode;
try {
GenericApiModel? apiResponse;
@@ -197,7 +318,13 @@ class AuthenticationRepoImp implements AuthenticationRepo {
await apiClient.post(
endpoint,
- body: isRegister ? newRequest : newRequest.toJson(),
+ body: isFormFamilyFile
+ ? familyRequest
+ : isRegister
+ ? newRequest
+ : isSwitchUser
+ ? switchRequest
+ : newRequest.toJson(),
onFailure: (error, statusCode, {messageStatus, failureType}) {
failure = failureType;
},
@@ -226,7 +353,6 @@ class AuthenticationRepoImp implements AuthenticationRepo {
@override
Future>> checkIfUserAgreed({required dynamic commonAuthanticatedRequest}) async {
commonAuthanticatedRequest['Region'] = 1;
- print("dsfsdd");
try {
GenericApiModel? apiResponse;
Failure? failure;
@@ -261,7 +387,6 @@ class AuthenticationRepoImp implements AuthenticationRepo {
@override
Future>> getUserAgreementContent({required dynamic commonAuthanticatedRequest}) async {
commonAuthanticatedRequest['Region'] = 1;
- print("dsfsdd");
try {
GenericApiModel? apiResponse;
Failure? failure;
diff --git a/lib/features/authentication/authentication_view_model.dart b/lib/features/authentication/authentication_view_model.dart
index b43858c..e643c5d 100644
--- a/lib/features/authentication/authentication_view_model.dart
+++ b/lib/features/authentication/authentication_view_model.dart
@@ -13,6 +13,7 @@ import 'package:hmg_patient_app_new/core/common_models/nationality_country_model
import 'package:hmg_patient_app_new/core/common_models/privilege/HMCProjectListModel.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';
@@ -26,6 +27,9 @@ import 'package:hmg_patient_app_new/features/authentication/models/resp_models/a
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/features/medical_file/medical_file_view_model.dart';
+import 'package:hmg_patient_app_new/features/my_appointments/my_appointments_view_model.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';
@@ -243,7 +247,7 @@ class AuthenticationViewModel extends ChangeNotifier {
await selectDeviceImei(onSuccess: (dynamic respData) async {
try {
if (respData != null) {
- dynamic data = SelectDeviceByImeiRespModelElement.fromJson(respData.toJson());
+ dynamic data = await SelectDeviceByImeiRespModelElement.fromJson(respData.toJson());
_appState.setSelectDeviceByImeiRespModelElement(data);
LoaderBottomSheet.hideLoader();
@@ -342,24 +346,33 @@ class AuthenticationViewModel extends ChangeNotifier {
);
}
- Future sendActivationCode(
- {required OTPTypeEnum otpTypeEnum, required String nationalIdOrFileNumber, required String phoneNumber, required bool isForRegister, dynamic payload, bool isComingFromResendOTP = false}) async {
+ Future 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,
- );
+ 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.countryCode
+ ? false
+ : true,
+ payload: payload,
+ isExcludedUser: isExcludedUser,
+ isFormFamilyFile: isFormFamilyFile,
+ responseID: responseID);
// TODO: GET APP SMS SIGNATURE HERE
request.sMSSignature = await getSignature();
@@ -368,11 +381,17 @@ class AuthenticationViewModel extends ChangeNotifier {
_appState.setUserRegistrationPayload = RegistrationDataModelPayload.fromJson(payload);
}
- final resultEither = await _authenticationRepo.sendActivationCodeRepo(sendActivationCodeReq: request, isRegister: checkIsUserComingForRegister(request: payload), languageID: 'er');
+ 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'];
+ _appState.setFamilyFileTokenID = apiResponse.data['LogInTokenID'];
+ }
if (apiResponse.messageStatus == 2) {
LoaderBottomSheet.hideLoader();
await _dialogService.showCommonBottomSheetWithoutH(
@@ -383,7 +402,18 @@ class AuthenticationViewModel extends ChangeNotifier {
} else {
if (apiResponse.data != null && apiResponse.data['isSMSSent'] == true) {
LoaderBottomSheet.hideLoader();
- if (!isComingFromResendOTP) navigateToOTPScreen(otpTypeEnum: otpTypeEnum, phoneNumber: phoneNumber, isComingFromRegister: checkIsUserComingForRegister(request: payload), payload: payload);
+ 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);
@@ -401,8 +431,17 @@ class AuthenticationViewModel extends ChangeNotifier {
return isUserComingForRegister;
}
- Future checkActivationCode(
- {required String? activationCode, required OTPTypeEnum otpTypeEnum, required Function(String? message) onWrongActivationCode, Function()? onResendActivation}) async {
+ Future checkActivationCode({
+ required String? activationCode,
+ required OTPTypeEnum otpTypeEnum,
+ required Function(String? message) onWrongActivationCode,
+ Function()? onResendActivation,
+ bool isFormFamilyFile = false,
+ dynamic patientShareRequestID,
+ dynamic responseID,
+ bool isSwitchUser = false,
+ int? patientID,
+ }) async {
bool isForRegister = (_appState.getUserRegistrationPayload.healthId != null || _appState.getUserRegistrationPayload.patientOutSa == true || _appState.getUserRegistrationPayload.patientOutSa == 1);
final request = RequestUtils.getCommonRequestWelcome(
@@ -428,6 +467,7 @@ class AuthenticationViewModel extends ChangeNotifier {
//TODO: Error Here IN Zip Code.
loginType: loginTypeEnum.toInt)
.toJson();
+
LoaderBottomSheet.showLoader();
if (isForRegister) {
if (_appState.getUserRegistrationPayload.patientOutSa == 0) request['DOB'] = _appState.getUserRegistrationPayload.dob;
@@ -463,7 +503,17 @@ class AuthenticationViewModel extends ChangeNotifier {
}
});
} else {
- final resultEither = await _authenticationRepo.checkActivationCodeRepo(newRequest: CheckActivationCodeRegisterReq.fromJson(request), activationCode: activationCode, isRegister: false);
+ final resultEither = await _authenticationRepo.checkActivationCodeRepo(
+ newRequest: CheckActivationCodeRegisterReq.fromJson(request),
+ activationCode: activationCode,
+ isRegister: false,
+ isFormFamilyFile: isFormFamilyFile,
+ patientShareRequestID: patientShareRequestID,
+ responseID: responseID,
+ isSwitchUser: isSwitchUser,
+ patientID: patientID,
+ loginType: _appState.getSuperUserID != null ? 0 : 2,
+ );
resultEither.fold(
(failure) async => await _errorHandlerService.handleError(
@@ -494,48 +544,86 @@ class AuthenticationViewModel extends ChangeNotifier {
// 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();
+ if (isFormFamilyFile) {
+ // await navigateToFamilyFilePage();
+ MedicalFileViewModel medicalVm = getIt();
+ if (!_appState.getIsChildLoggedIn) {
+ await medicalVm.getFamilyFiles(status: 0);
+ await medicalVm.getAllPendingRecordsByResponseId();
+ _navigationService.popUntilNamed(AppRoutes.landingScreen);
+ }
} else {
- navigateToHomeScreen();
- //Agreement page not designed yet so we are navigating to home screen directly
- // getUserAgreementContent(request: request);
+ if (activation.list != null && activation.list!.isNotEmpty) {
+ if (isSwitchUser) {
+ if (_appState.getIsChildLoggedIn) {
+ _appState.setSuperUserID = null;
+ _appState.setIsChildLoggedIn = false;
+ activation.list!.first.isParentUser = true;
+ } else {
+ _appState.setSuperUserID = _appState.getAuthenticatedUser()?.patientId;
+ _appState.setIsChildLoggedIn = true;
+ activation.list!.first.isParentUser = false;
+ }
+ } else {
+ activation.list!.first.isParentUser = true;
+ }
+ activation.list!.first.bloodGroup = activation.patientBlodType;
+ _appState.setAuthenticatedUser(activation.list!.first);
+ _appState.setPrivilegeModelList(activation.list!.first.listPrivilege!);
+ }
+ // _appState.setUserBloodGroup = (activation.patientBlodType ?? "");
+ _appState.setAppAuthToken = activation.authenticationTokenId;
+ final request = await 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();
+//
+ if (!isSwitchUser && !_appState.getIsChildLoggedIn) {
+ MedicalFileViewModel medicalVm = getIt();
+ await insertPatientIMEIData(loginTypeEnum.toInt);
+ await medicalVm.getFamilyFiles(status: 0); //TODO: Remove status: 1 by Aamir Need to Discuss With Sultan
+ await medicalVm.getAllPendingRecordsByResponseId();
+ }
+
+ await clearDefaultInputValues();
+ if (isUserAgreedBefore) {
+ navigateToHomeScreen();
+ } else {
+ MyAppointmentsViewModel myAppointmentsVM = getIt();
+ myAppointmentsVM.setIsAppointmentDataToBeLoaded(true);
+ 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();
}
- // 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 navigateToFamilyFilePage() async {
+ MedicalFileViewModel medicalFileVM = GetIt.instance();
+ medicalFileVM.handleFamilyFileRequestOTPVerification();
+ }
+
Future checkIfUserAgreedBefore({required dynamic request}) async {
bool isAgreed = false;
if (havePrivilege(109)) {
@@ -573,13 +661,25 @@ class AuthenticationViewModel extends ChangeNotifier {
_navigationService.pushAndReplace(AppRoutes.landingScreen);
}
- Future navigateToOTPScreen({required OTPTypeEnum otpTypeEnum, required String phoneNumber, required bool isComingFromRegister, dynamic payload}) async {
+ Future 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);
},
@@ -587,12 +687,16 @@ class AuthenticationViewModel extends ChangeNotifier {
},
onResendOTPPressed: (String phoneNumber) async {
await sendActivationCode(
- otpTypeEnum: otpTypeEnum,
- phoneNumber: phoneNumberController.text,
- nationalIdOrFileNumber: nationalIdController.text,
- isForRegister: isComingFromRegister,
- isComingFromResendOTP: true,
- payload: payload);
+ otpTypeEnum: otpTypeEnum,
+ phoneNumber: phoneNumberController.text,
+ nationalIdOrFileNumber: nationalIdController.text,
+ isForRegister: isComingFromRegister,
+ isComingFromResendOTP: true,
+ payload: payload,
+ isFormFamilyFile: isFormFamilyFile,
+ isExcludedUser: isExcludedUser,
+ responseID: responseID,
+ );
},
);
}
diff --git a/lib/features/authentication/models/resp_models/authenticated_user_resp_model.dart b/lib/features/authentication/models/resp_models/authenticated_user_resp_model.dart
index 8848fde..8209a0f 100644
--- a/lib/features/authentication/models/resp_models/authenticated_user_resp_model.dart
+++ b/lib/features/authentication/models/resp_models/authenticated_user_resp_model.dart
@@ -69,6 +69,8 @@ class AuthenticatedUser {
dynamic authenticatedUserPatientPayType;
dynamic authenticatedUserPatientType;
dynamic authenticatedUserStatus;
+ int? superUser;
+ bool? isParentUser;
AuthenticatedUser({
this.setupId,
@@ -139,6 +141,8 @@ class AuthenticatedUser {
this.authenticatedUserPatientPayType,
this.authenticatedUserPatientType,
this.authenticatedUserStatus,
+ this.superUser,
+ this.isParentUser,
});
factory AuthenticatedUser.fromRawJson(String str) => AuthenticatedUser.fromJson(json.decode(str));
@@ -146,146 +150,150 @@ class AuthenticatedUser {
String toRawJson() => json.encode(toJson());
factory AuthenticatedUser.fromJson(Map json) => AuthenticatedUser(
- setupId: json["SetupID"],
- patientType: json["PatientType"],
- patientId: json["PatientID"],
- firstName: json["FirstName"],
- middleName: json["MiddleName"],
- lastName: json["LastName"],
- firstNameN: json["FirstNameN"],
- middleNameN: json["MiddleNameN"],
- lastNameN: json["LastNameN"],
- relationshipId: json["RelationshipID"],
- gender: json["Gender"],
- dateofBirth: json["DateofBirth"],
- dateofBirthN: json["DateofBirthN"],
- nationalityId: json["NationalityID"],
- phoneResi: json["PhoneResi"],
- phoneOffice: json["PhoneOffice"],
- mobileNumber: json["MobileNumber"],
- faxNumber: json["FaxNumber"],
- emailAddress: json["EmailAddress"],
- bloodGroup: json["BloodGroup"],
- rhFactor: json["RHFactor"],
- isEmailAlertRequired: json["IsEmailAlertRequired"],
- isSmsAlertRequired: json["IsSMSAlertRequired"],
- preferredLanguage: json["PreferredLanguage"],
- isPrivilegedMember: json["IsPrivilegedMember"],
- memberId: json["MemberID"],
- expiryDate: json["ExpiryDate"],
- isHmgEmployee: json["IsHmgEmployee"],
- employeeId: json["EmployeeID"],
- emergencyContactName: json["EmergencyContactName"],
- emergencyContactNo: json["EmergencyContactNo"],
- patientPayType: json["PatientPayType"],
- dhccPatientRefId: json["DHCCPatientRefID"],
- isPatientDummy: json["IsPatientDummy"],
- status: json["Status"],
- isStatusCleared: json["IsStatusCleared"],
- patientIdentificationType: json["PatientIdentificationType"],
- patientIdentificationNo: json["PatientIdentificationNo"],
- projectId: json["ProjectID"],
- infoSourceId: json["InfoSourceID"],
- address: json["Address"],
- age: json["Age"],
- ageDesc: json["AgeDesc"],
- areaId: json["AreaID"],
- crsVerificationStatus: json["CRSVerificationStatus"],
- crsVerificationStatusDesc: json["CRSVerificationStatusDesc"],
- crsVerificationStatusDescN: json["CRSVerificationStatusDescN"],
- createdBy: json["CreatedBy"],
- genderDescription: json["GenderDescription"],
- healthIdFromNhicViaVida: json["HealthIDFromNHICViaVida"],
- ir: json["IR"],
- isoCityId: json["ISOCityID"],
- isoCountryId: json["ISOCountryID"],
- isVerfiedFromNhic: json["IsVerfiedFromNHIC"],
- listPrivilege: json["ListPrivilege"] == null ? [] : List.from(json["ListPrivilege"]!.map((x) => ListPrivilege.fromJson(x))),
- marital: json["Marital"],
- occupationId: json["OccupationID"],
- outSa: json["OutSA"],
- poBox: json["POBox"],
- receiveHealthSummaryReport: json["ReceiveHealthSummaryReport"],
- sourceType: json["SourceType"],
- strDateofBirth: json["StrDateofBirth"],
- tempAddress: json["TempAddress"],
- zipCode: json["ZipCode"],
- eHealthIdField: json["eHealthIDField"],
- authenticatedUserPatientPayType: json["patientPayType"],
- authenticatedUserPatientType: json["patientType"],
- authenticatedUserStatus: json["status"],
- );
+ setupId: json["SetupID"],
+ patientType: json["PatientType"],
+ patientId: json["PatientID"],
+ firstName: json["FirstName"],
+ middleName: json["MiddleName"],
+ lastName: json["LastName"],
+ firstNameN: json["FirstNameN"],
+ middleNameN: json["MiddleNameN"],
+ lastNameN: json["LastNameN"],
+ relationshipId: json["RelationshipID"],
+ gender: json["Gender"],
+ dateofBirth: json["DateofBirth"],
+ dateofBirthN: json["DateofBirthN"],
+ nationalityId: json["NationalityID"],
+ phoneResi: json["PhoneResi"],
+ phoneOffice: json["PhoneOffice"],
+ mobileNumber: json["MobileNumber"],
+ faxNumber: json["FaxNumber"],
+ emailAddress: json["EmailAddress"],
+ bloodGroup: json["BloodGroup"],
+ rhFactor: json["RHFactor"],
+ isEmailAlertRequired: json["IsEmailAlertRequired"],
+ isSmsAlertRequired: json["IsSMSAlertRequired"],
+ preferredLanguage: json["PreferredLanguage"],
+ isPrivilegedMember: json["IsPrivilegedMember"],
+ memberId: json["MemberID"],
+ expiryDate: json["ExpiryDate"],
+ isHmgEmployee: json["IsHmgEmployee"],
+ employeeId: json["EmployeeID"],
+ emergencyContactName: json["EmergencyContactName"],
+ emergencyContactNo: json["EmergencyContactNo"],
+ patientPayType: json["PatientPayType"],
+ dhccPatientRefId: json["DHCCPatientRefID"],
+ isPatientDummy: json["IsPatientDummy"],
+ status: json["Status"],
+ isStatusCleared: json["IsStatusCleared"],
+ patientIdentificationType: json["PatientIdentificationType"],
+ patientIdentificationNo: json["PatientIdentificationNo"],
+ projectId: json["ProjectID"],
+ infoSourceId: json["InfoSourceID"],
+ address: json["Address"],
+ age: json["Age"],
+ ageDesc: json["AgeDesc"],
+ areaId: json["AreaID"],
+ crsVerificationStatus: json["CRSVerificationStatus"],
+ crsVerificationStatusDesc: json["CRSVerificationStatusDesc"],
+ crsVerificationStatusDescN: json["CRSVerificationStatusDescN"],
+ createdBy: json["CreatedBy"],
+ genderDescription: json["GenderDescription"],
+ healthIdFromNhicViaVida: json["HealthIDFromNHICViaVida"],
+ ir: json["IR"],
+ isoCityId: json["ISOCityID"],
+ isoCountryId: json["ISOCountryID"],
+ isVerfiedFromNhic: json["IsVerfiedFromNHIC"],
+ listPrivilege: json["ListPrivilege"] == null ? [] : List.from(json["ListPrivilege"]!.map((x) => ListPrivilege.fromJson(x))),
+ marital: json["Marital"],
+ occupationId: json["OccupationID"],
+ outSa: json["OutSA"],
+ poBox: json["POBox"],
+ receiveHealthSummaryReport: json["ReceiveHealthSummaryReport"],
+ sourceType: json["SourceType"],
+ strDateofBirth: json["StrDateofBirth"],
+ tempAddress: json["TempAddress"],
+ zipCode: json["ZipCode"],
+ eHealthIdField: json["eHealthIDField"],
+ authenticatedUserPatientPayType: json["patientPayType"],
+ authenticatedUserPatientType: json["patientType"],
+ authenticatedUserStatus: json["status"],
+ superUser: json["superUser"],
+ isParentUser: json["isParentUser"] ?? false,
+ );
Map toJson() => {
- "SetupID": setupId,
- "PatientType": patientType,
- "PatientID": patientId,
- "FirstName": firstName,
- "MiddleName": middleName,
- "LastName": lastName,
- "FirstNameN": firstNameN,
- "MiddleNameN": middleNameN,
- "LastNameN": lastNameN,
- "RelationshipID": relationshipId,
- "Gender": gender,
- "DateofBirth": dateofBirth,
- "DateofBirthN": dateofBirthN,
- "NationalityID": nationalityId,
- "PhoneResi": phoneResi,
- "PhoneOffice": phoneOffice,
- "MobileNumber": mobileNumber,
- "FaxNumber": faxNumber,
- "EmailAddress": emailAddress,
- "BloodGroup": bloodGroup,
- "RHFactor": rhFactor,
- "IsEmailAlertRequired": isEmailAlertRequired,
- "IsSMSAlertRequired": isSmsAlertRequired,
- "PreferredLanguage": preferredLanguage,
- "IsPrivilegedMember": isPrivilegedMember,
- "MemberID": memberId,
- "ExpiryDate": expiryDate,
- "IsHmgEmployee": isHmgEmployee,
- "EmployeeID": employeeId,
- "EmergencyContactName": emergencyContactName,
- "EmergencyContactNo": emergencyContactNo,
- "PatientPayType": patientPayType,
- "DHCCPatientRefID": dhccPatientRefId,
- "IsPatientDummy": isPatientDummy,
- "Status": status,
- "IsStatusCleared": isStatusCleared,
- "PatientIdentificationType": patientIdentificationType,
- "PatientIdentificationNo": patientIdentificationNo,
- "ProjectID": projectId,
- "InfoSourceID": infoSourceId,
- "Address": address,
- "Age": age,
- "AgeDesc": ageDesc,
- "AreaID": areaId,
- "CRSVerificationStatus": crsVerificationStatus,
- "CRSVerificationStatusDesc": crsVerificationStatusDesc,
- "CRSVerificationStatusDescN": crsVerificationStatusDescN,
- "CreatedBy": createdBy,
- "GenderDescription": genderDescription,
- "HealthIDFromNHICViaVida": healthIdFromNhicViaVida,
- "IR": ir,
- "ISOCityID": isoCityId,
- "ISOCountryID": isoCountryId,
- "IsVerfiedFromNHIC": isVerfiedFromNhic,
- "ListPrivilege": listPrivilege == null ? [] : List.from(listPrivilege!.map((x) => x.toJson())),
- "Marital": marital,
- "OccupationID": occupationId,
- "OutSA": outSa,
- "POBox": poBox,
- "ReceiveHealthSummaryReport": receiveHealthSummaryReport,
- "SourceType": sourceType,
- "StrDateofBirth": strDateofBirth,
- "TempAddress": tempAddress,
- "ZipCode": zipCode,
- "eHealthIDField": eHealthIdField,
- "patientPayType": authenticatedUserPatientPayType,
- "patientType": authenticatedUserPatientType,
- "status": authenticatedUserStatus,
- };
+ "SetupID": setupId,
+ "PatientType": patientType,
+ "PatientID": patientId,
+ "FirstName": firstName,
+ "MiddleName": middleName,
+ "LastName": lastName,
+ "FirstNameN": firstNameN,
+ "MiddleNameN": middleNameN,
+ "LastNameN": lastNameN,
+ "RelationshipID": relationshipId,
+ "Gender": gender,
+ "DateofBirth": dateofBirth,
+ "DateofBirthN": dateofBirthN,
+ "NationalityID": nationalityId,
+ "PhoneResi": phoneResi,
+ "PhoneOffice": phoneOffice,
+ "MobileNumber": mobileNumber,
+ "FaxNumber": faxNumber,
+ "EmailAddress": emailAddress,
+ "BloodGroup": bloodGroup,
+ "RHFactor": rhFactor,
+ "IsEmailAlertRequired": isEmailAlertRequired,
+ "IsSMSAlertRequired": isSmsAlertRequired,
+ "PreferredLanguage": preferredLanguage,
+ "IsPrivilegedMember": isPrivilegedMember,
+ "MemberID": memberId,
+ "ExpiryDate": expiryDate,
+ "IsHmgEmployee": isHmgEmployee,
+ "EmployeeID": employeeId,
+ "EmergencyContactName": emergencyContactName,
+ "EmergencyContactNo": emergencyContactNo,
+ "PatientPayType": patientPayType,
+ "DHCCPatientRefID": dhccPatientRefId,
+ "IsPatientDummy": isPatientDummy,
+ "Status": status,
+ "IsStatusCleared": isStatusCleared,
+ "PatientIdentificationType": patientIdentificationType,
+ "PatientIdentificationNo": patientIdentificationNo,
+ "ProjectID": projectId,
+ "InfoSourceID": infoSourceId,
+ "Address": address,
+ "Age": age,
+ "AgeDesc": ageDesc,
+ "AreaID": areaId,
+ "CRSVerificationStatus": crsVerificationStatus,
+ "CRSVerificationStatusDesc": crsVerificationStatusDesc,
+ "CRSVerificationStatusDescN": crsVerificationStatusDescN,
+ "CreatedBy": createdBy,
+ "GenderDescription": genderDescription,
+ "HealthIDFromNHICViaVida": healthIdFromNhicViaVida,
+ "IR": ir,
+ "ISOCityID": isoCityId,
+ "ISOCountryID": isoCountryId,
+ "IsVerfiedFromNHIC": isVerfiedFromNhic,
+ "ListPrivilege": listPrivilege == null ? [] : List.from(listPrivilege!.map((x) => x.toJson())),
+ "Marital": marital,
+ "OccupationID": occupationId,
+ "OutSA": outSa,
+ "POBox": poBox,
+ "ReceiveHealthSummaryReport": receiveHealthSummaryReport,
+ "SourceType": sourceType,
+ "StrDateofBirth": strDateofBirth,
+ "TempAddress": tempAddress,
+ "ZipCode": zipCode,
+ "eHealthIDField": eHealthIdField,
+ "patientPayType": authenticatedUserPatientPayType,
+ "patientType": authenticatedUserPatientType,
+ "status": authenticatedUserStatus,
+ "superUser": superUser,
+ "isParentUser": isParentUser,
+ };
}
class ListPrivilege {
@@ -306,16 +314,16 @@ class ListPrivilege {
String toRawJson() => json.encode(toJson());
factory ListPrivilege.fromJson(Map json) => ListPrivilege(
- id: json["ID"],
- serviceName: json["ServiceName"],
- previlege: json["Previlege"],
- region: json["Region"],
- );
+ id: json["ID"],
+ serviceName: json["ServiceName"],
+ previlege: json["Previlege"],
+ region: json["Region"],
+ );
Map toJson() => {
- "ID": id,
- "ServiceName": serviceName,
- "Previlege": previlege,
- "Region": region,
- };
+ "ID": id,
+ "ServiceName": serviceName,
+ "Previlege": previlege,
+ "Region": region,
+ };
}
diff --git a/lib/features/authentication/widgets/otp_verification_screen.dart b/lib/features/authentication/widgets/otp_verification_screen.dart
index e7f8d72..10e34cd 100644
--- a/lib/features/authentication/widgets/otp_verification_screen.dart
+++ b/lib/features/authentication/widgets/otp_verification_screen.dart
@@ -428,13 +428,9 @@ class OTPVerificationScreen extends StatefulWidget {
final String phoneNumber;
final Function(int code) checkActivationCode;
final Function(String phoneNumber) onResendOTPPressed;
+ final bool isFormFamilyFile;
- const OTPVerificationScreen({
- super.key,
- required this.phoneNumber,
- required this.checkActivationCode,
- required this.onResendOTPPressed,
- });
+ const OTPVerificationScreen({super.key, required this.phoneNumber, required this.checkActivationCode, required this.onResendOTPPressed, required this.isFormFamilyFile});
@override
State createState() => _OTPVerificationScreenState();
@@ -559,7 +555,7 @@ class _OTPVerificationScreenState extends State {
LocaleKeys.weHaveSendOTP.tr().toText15(color: AppColors.inputLabelTextColor, letterSpacing: -0.4),
_getMaskedPhoneNumber().toText15(color: AppColors.inputLabelTextColor, isBold: true),
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
? LocaleKeys.forRegistrationVerification.tr().toText15(color: AppColors.inputLabelTextColor, letterSpacing: -0.4)
: LocaleKeys.forLoginVerification.tr().toText15(color: AppColors.inputLabelTextColor, letterSpacing: -0.4),
diff --git a/lib/features/common/models/family_file_request.dart b/lib/features/common/models/family_file_request.dart
new file mode 100644
index 0000000..047b9af
--- /dev/null
+++ b/lib/features/common/models/family_file_request.dart
@@ -0,0 +1,57 @@
+import 'dart:convert';
+
+class FamilyFileRequest {
+ int? sharedPatientId;
+ String? sharedPatientIdentificationId;
+ int? searchType;
+ String? sharedPatientMobileNumber;
+ String? zipCode;
+ bool? isRegister;
+ int? patientStatus;
+ bool? isDentalAllowedBackend;
+ bool? isPatientExcluded;
+ int? responseID;
+
+ FamilyFileRequest({
+ this.sharedPatientId,
+ this.sharedPatientIdentificationId,
+ this.searchType,
+ this.sharedPatientMobileNumber,
+ this.zipCode,
+ this.isRegister,
+ this.patientStatus,
+ this.isDentalAllowedBackend,
+ this.isPatientExcluded,
+ this.responseID,
+ });
+
+ factory FamilyFileRequest.fromRawJson(String str) => FamilyFileRequest.fromJson(json.decode(str));
+
+ String toRawJson() => json.encode(toJson());
+
+ factory FamilyFileRequest.fromJson(Map json) => FamilyFileRequest(
+ sharedPatientId: json["sharedPatientID"],
+ sharedPatientIdentificationId: json["sharedPatientIdentificationID"],
+ searchType: json["searchType"],
+ sharedPatientMobileNumber: json["sharedPatientMobileNumber"],
+ zipCode: json["zipCode"],
+ isRegister: json["isRegister"],
+ patientStatus: json["patientStatus"],
+ isDentalAllowedBackend: json["isDentalAllowedBackend"],
+ isPatientExcluded: json["IsPatientExcluded"],
+ responseID: json["ReponseID"],
+ );
+
+ Map toJson() => {
+ "SharedPatientID": sharedPatientId,
+ "SharedPatientIdentificationID": sharedPatientIdentificationId,
+ "SearchType": searchType,
+ "SharedPatientMobileNumber": sharedPatientMobileNumber,
+ "zipCode": zipCode,
+ "isRegister": isRegister,
+ "PatientStatus": patientStatus,
+ "isDentalAllowedBackend": isDentalAllowedBackend,
+ "IsPatientExcluded": isPatientExcluded,
+ "ReponseID": responseID,
+ };
+}
diff --git a/lib/features/medical_file/medical_file_repo.dart b/lib/features/medical_file/medical_file_repo.dart
index 7077fd0..a460d9f 100644
--- a/lib/features/medical_file/medical_file_repo.dart
+++ b/lib/features/medical_file/medical_file_repo.dart
@@ -25,13 +25,19 @@ abstract class MedicalFileRepo {
Future>> getPatientMedicalReportPDF(PatientMedicalReportResponseModel patientMedicalReportResponseModel, AuthenticatedUser authenticatedUser);
- Future>>> getPatientFamilyFiles();
+ Future>>> getPatientFamilyFiles(int? status, int patientId);
- Future>>> addFamilyFile({required dynamic request});
+ Future>>> getAllPendingRecordsByResponseId({required Map request});
+
+ Future>> addFamilyFile({required dynamic request});
Future>>> getPatientAppointmentsForMedicalReport();
Future>> insertRequestForMedicalReport({required PatientAppointmentHistoryResponseModel appointmentHistoryResponseModel});
+
+ Future>> removeFamilyFile({required int? id});
+
+ Future>> acceptRejectFamilyFile({required int? id, required int? status});
}
class MedicalFileRepoImp implements MedicalFileRepo {
@@ -279,13 +285,13 @@ class MedicalFileRepoImp implements MedicalFileRepo {
}
@override
- Future>>> getPatientFamilyFiles() async {
+ Future>>> getPatientFamilyFiles(int? status, int patientID) async {
try {
GenericApiModel>? apiResponse;
Failure? failure;
await apiClient.post(
- FAMILY_FILES,
- body: {"Status": 3},
+ ApiConsts.getAllSharedRecordsByStatus,
+ body: {if (status != null) "Status": status, "PatientID": patientID},
onFailure: (error, statusCode, {messageStatus, failureType}) {
failure = failureType;
},
@@ -318,9 +324,44 @@ class MedicalFileRepoImp implements MedicalFileRepo {
}
@override
- Future>>> addFamilyFile({dynamic request}) async {
+ Future>>> getAllPendingRecordsByResponseId({required Map request}) async {
try {
- GenericApiModel>? apiResponse;
+ GenericApiModel>? apiResponse;
+ Failure? failure;
+ await apiClient.post(
+ ApiConsts.getAllPendingRecordsByResponseId,
+ body: request,
+ onFailure: (error, statusCode, {messageStatus, failureType}) {
+ failure = failureType;
+ },
+ onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
+ try {
+ final list = response['GetAllPendingRecordsList'];
+ final familyLists = list.map((item) => FamilyFileResponseModelLists.fromJson(item as Map)).toList().cast();
+
+ apiResponse = GenericApiModel>(
+ messageStatus: messageStatus,
+ statusCode: statusCode,
+ errorMessage: null,
+ data: familyLists,
+ );
+ } catch (e) {
+ failure = DataParsingFailure(e.toString());
+ }
+ },
+ );
+ if (failure != null) return Left(failure!);
+ if (apiResponse == null) return Left(ServerFailure("Unknown error"));
+ return Right(apiResponse!);
+ } catch (e) {
+ return Left(UnknownFailure(e.toString()));
+ }
+ }
+
+ @override
+ Future>> addFamilyFile({dynamic request}) async {
+ try {
+ GenericApiModel? apiResponse;
Failure? failure;
await apiClient.post(
ApiConsts.addFamilyFile,
@@ -330,17 +371,82 @@ class MedicalFileRepoImp implements MedicalFileRepo {
},
onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
try {
- print(response);
- // final list = response['GetAllSharedRecordsByStatusList'];
- //
- // final familyLists = list.map((item) => FamilyFileResponseModelLists.fromJson(item as Map)).toList().cast();
- //
- // apiResponse = GenericApiModel>(
- // messageStatus: messageStatus,
- // statusCode: statusCode,
- // errorMessage: null,
- // data: familyLists,
- // );
+ apiResponse = GenericApiModel(
+ messageStatus: messageStatus,
+ statusCode: statusCode,
+ errorMessage: errorMessage,
+ data: response["ShareFamilyFileObj"] ?? null,
+ );
+ } catch (e) {
+ failure = DataParsingFailure(e.toString());
+ }
+ },
+ );
+ if (failure != null) return Left(failure!);
+ if (apiResponse == null) return Left(ServerFailure("Unknown error"));
+ return Right(apiResponse!);
+ } catch (e) {
+ return Left(UnknownFailure(e.toString()));
+ }
+ }
+
+ @override
+ Future>> removeFamilyFile({required int? id}) async {
+ Map request = {};
+ request["ID"] = id;
+ request['IsActive'] = false;
+ try {
+ GenericApiModel? apiResponse;
+ Failure? failure;
+ await apiClient.post(
+ ApiConsts.removeFileFromFamilyMembers,
+ body: request,
+ onFailure: (error, statusCode, {messageStatus, failureType}) {
+ failure = failureType;
+ },
+ onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
+ try {
+ apiResponse = GenericApiModel(
+ messageStatus: messageStatus,
+ statusCode: statusCode,
+ errorMessage: errorMessage,
+ data: response,
+ );
+ } catch (e) {
+ failure = DataParsingFailure(e.toString());
+ }
+ },
+ );
+ if (failure != null) return Left(failure!);
+ if (apiResponse == null) return Left(ServerFailure("Unknown error"));
+ return Right(apiResponse!);
+ } catch (e) {
+ return Left(UnknownFailure(e.toString()));
+ }
+ }
+
+ @override
+ Future>> acceptRejectFamilyFile({required int? id, required int? status}) async {
+ Map request = {};
+ request["ID"] = id;
+ request['Status'] = status;
+ try {
+ GenericApiModel? apiResponse;
+ Failure? failure;
+ await apiClient.post(
+ ApiConsts.acceptAndRejectFamilyFile,
+ body: request,
+ onFailure: (error, statusCode, {messageStatus, failureType}) {
+ failure = failureType;
+ },
+ onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
+ try {
+ apiResponse = GenericApiModel(
+ messageStatus: messageStatus,
+ statusCode: statusCode,
+ errorMessage: errorMessage,
+ data: response,
+ );
} catch (e) {
failure = DataParsingFailure(e.toString());
}
diff --git a/lib/features/medical_file/medical_file_view_model.dart b/lib/features/medical_file/medical_file_view_model.dart
index 3f0573f..b5d9d03 100644
--- a/lib/features/medical_file/medical_file_view_model.dart
+++ b/lib/features/medical_file/medical_file_view_model.dart
@@ -1,7 +1,15 @@
+import 'dart:convert';
+import 'dart:developer';
+
import 'package:flutter/material.dart';
import 'package:hmg_patient_app_new/core/app_state.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/request_utils.dart';
+import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
+import 'package:hmg_patient_app_new/features/authentication/authentication_view_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/common/models/family_file_request.dart';
import 'package:hmg_patient_app_new/features/medical_file/medical_file_repo.dart';
import 'package:hmg_patient_app_new/features/medical_file/models/family_file_response_model.dart';
import 'package:hmg_patient_app_new/features/medical_file/models/patient_medical_response_model.dart';
@@ -10,6 +18,8 @@ import 'package:hmg_patient_app_new/features/medical_file/models/patient_vaccine
import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/patient_appointment_history_response_model.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/navigation_service.dart';
+import 'package:hmg_patient_app_new/widgets/loader/bottomsheet_loader.dart';
class MedicalFileViewModel extends ChangeNotifier {
int selectedTabIndex = 0;
@@ -34,13 +44,26 @@ class MedicalFileViewModel extends ChangeNotifier {
PatientAppointmentHistoryResponseModel? patientMedicalReportSelectedAppointment;
List patientFamilyFiles = [];
+ List pendingFamilyFiles = [];
String patientSickLeavePDFBase64 = "";
String patientMedicalReportPDFBase64 = "";
int selectedMedicalReportsTabIndex = 0;
+ int _selectedFamilyFileTabIndex = 0;
+
+ int get getSelectedFamilyFileTabIndex => _selectedFamilyFileTabIndex;
+
+ set setSelectedFamilyFileTabIndex(int value) {
+ if (_selectedFamilyFileTabIndex != value) {
+ _selectedFamilyFileTabIndex = value;
+ notifyListeners();
+ }
+ }
+
static final DialogService _dialogService = getIt.get();
- AppState _appState = getIt();
+ final AppState _appState = getIt();
+ AuthenticationViewModel authVM = getIt.get();
MedicalFileViewModel({required this.medicalFileRepo, required this.errorHandlerService});
@@ -64,6 +87,11 @@ class MedicalFileViewModel extends ChangeNotifier {
notifyListeners();
}
+ void onFamilyFileTabChange(int index) {
+ setSelectedFamilyFileTabIndex = index;
+ notifyListeners();
+ }
+
setIsPatientVaccineListLoading(bool isLoading) {
isPatientVaccineListLoading = isLoading;
notifyListeners();
@@ -247,8 +275,8 @@ class MedicalFileViewModel extends ChangeNotifier {
);
}
- Future getFamilyFiles({Function(dynamic)? onSuccess, Function(String)? onError}) async {
- final result = await medicalFileRepo.getPatientFamilyFiles();
+ Future getFamilyFiles({int? status, Function(dynamic)? onSuccess, Function(String)? onError}) async {
+ final result = await medicalFileRepo.getPatientFamilyFiles(status, _appState.getSuperUserID != null ? _appState.getSuperUserID! : _appState.getAuthenticatedUser()!.patientId!);
result.fold(
(failure) async => await errorHandlerService.handleError(
@@ -261,16 +289,85 @@ class MedicalFileViewModel extends ChangeNotifier {
if (apiResponse.messageStatus == 2) {
_dialogService.showErrorBottomSheet(message: apiResponse.errorMessage!, onOkPressed: () {});
} else if (apiResponse.messageStatus == 1) {
- patientFamilyFiles = apiResponse.data!;
- patientFamilyFiles.insert(
- 0,
- FamilyFileResponseModelLists(
- patientId: _appState.getAuthenticatedUser()!.patientId,
- patientName: '${_appState.getAuthenticatedUser()!.firstName!} ${_appState.getAuthenticatedUser()!.lastName!}',
- isActive: true,
- gender: _appState.getAuthenticatedUser()!.gender!,
- responseId: _appState.getAuthenticatedUser()!.patientId),
- );
+ if (apiResponse.data != null) {
+ // Add current user as the first active family file
+ final currentUser = _appState.getAuthenticatedUser()!;
+ final currentUserFamilyFile = FamilyFileResponseModelLists(
+ patientId: currentUser.patientId,
+ patientName: '${currentUser.firstName!} ${currentUser.lastName!}',
+ isActive: true,
+ gender: currentUser.gender!,
+ responseId: currentUser.patientId,
+ age: currentUser.age,
+ mobileNumber: currentUser.mobileNumber,
+ patientIdenficationNumber: currentUser.patientIdentificationNo,
+ emaiLAddress: currentUser.emailAddress,
+ genderDescription: currentUser.genderDescription,
+ );
+
+ // Clear and start fresh with current user
+ patientFamilyFiles.clear();
+ patientFamilyFiles.add(currentUserFamilyFile);
+
+ final List activeFamilyFiles = [];
+ final List pendingFamilyFiles = [];
+
+ for (var element in apiResponse.data!) {
+ if (element.status == null) {
+ continue;
+ }
+
+ final isPending = element.status == FamilyFileEnum.pending.toInt || element.status == FamilyFileEnum.rejected.toInt;
+ final isActive = element.status == FamilyFileEnum.active.toInt;
+
+ if (!isPending && !isActive) {
+ continue;
+ }
+
+ final familyFile = FamilyFileResponseModelLists(
+ id: element.id,
+ patientId: element.patientId,
+ patientName: element.patientName!,
+ isActive: element.isActive,
+ gender: element.gender!,
+ responseId: element.responseId,
+ mobileNumber: element.mobileNumber,
+ age: element.age,
+ patientIdenficationNumber: element.patientIdenficationNumber,
+ relationship: element.relationship,
+ relationshipId: element.relationshipId,
+ relationshipN: element.relationshipN,
+ status: element.status,
+ statusDescription: element.statusDescription,
+ createdOn: element.createdOn,
+ editedOn: element.editedOn,
+ patientDataVerified: element.patientDataVerified,
+ regionId: element.regionId,
+ familyRegionId: element.familyRegionId,
+ genderDescription: element.genderDescription,
+ genderImage: element.genderImage,
+ emaiLAddress: element.emaiLAddress,
+ );
+
+ if (isPending) {
+ familyFile.isRequestFromMySide = true;
+ pendingFamilyFiles.add(familyFile);
+ }
+ if (isActive) {
+ activeFamilyFiles.add(familyFile);
+ }
+ }
+
+ for (var activeFile in activeFamilyFiles) {
+ if (!patientFamilyFiles.any((e) => e.responseId == activeFile.responseId)) {
+ patientFamilyFiles.add(activeFile);
+ }
+ }
+
+ this.pendingFamilyFiles.clear();
+ this.pendingFamilyFiles.addAll(pendingFamilyFiles);
+ }
+
notifyListeners();
if (onSuccess != null) {
onSuccess(apiResponse);
@@ -280,39 +377,151 @@ class MedicalFileViewModel extends ChangeNotifier {
);
}
- Future switchFamilyFiles({Function(dynamic)? onSuccess, Function(String)? onError}) async {
- final result = await medicalFileRepo.getPatientFamilyFiles();
+ Future getAllPendingRecordsByResponseId() async {
+ AppState appState = getIt();
+ final result = await medicalFileRepo.getAllPendingRecordsByResponseId(request: {'ResponseID': appState.getAuthenticatedUser()!.patientId ?? "0", "Status": 2});
result.fold(
- (failure) async => await errorHandlerService.handleError(
- failure: failure,
- onOkPressed: () {
- onError!(failure.message);
- },
- ),
+ (failure) async => await errorHandlerService.handleError(failure: failure),
(apiResponse) {
if (apiResponse.messageStatus == 2) {
_dialogService.showErrorBottomSheet(message: apiResponse.errorMessage!, onOkPressed: () {});
} else if (apiResponse.messageStatus == 1) {
- patientFamilyFiles = apiResponse.data!;
- patientFamilyFiles.insert(
- 0,
- FamilyFileResponseModelLists(
- patientId: _appState.getAuthenticatedUser()!.patientId,
- patientName: '${_appState.getAuthenticatedUser()!.firstName!} ${_appState.getAuthenticatedUser()!.lastName!}',
- isActive: true,
- gender: _appState.getAuthenticatedUser()!.gender!,
- responseId: _appState.getAuthenticatedUser()!.patientId),
- );
- notifyListeners();
- if (onSuccess != null) {
- onSuccess(apiResponse);
+ if (apiResponse.data != null) {
+ final List tempPendingFamilyFiles = [];
+ for (var element in apiResponse.data!) {
+ if (element.status != null && element.status == FamilyFileEnum.pending.toInt || element.status == FamilyFileEnum.active.toInt) {
+ tempPendingFamilyFiles.add(FamilyFileResponseModelLists(
+ id: element.id,
+ patientId: element.patientId,
+ patientName: element.patientName!,
+ isActive: element.status,
+ gender: element.gender,
+ responseId: element.patientId,
+ mobileNumber: element.mobileNumber,
+ age: element.age,
+ patientIdenficationNumber: element.patientIdenficationNumber,
+ relationship: element.relationship,
+ relationshipId: element.relationshipId,
+ relationshipN: element.relationshipN,
+ status: element.status,
+ statusDescription: element.statusDescription,
+ createdOn: element.createdOn,
+ editedOn: element.editedOn,
+ patientDataVerified: element.patientDataVerified,
+ regionId: element.regionId,
+ familyRegionId: element.familyRegionId,
+ genderDescription: element.genderDescription,
+ genderImage: element.genderImage,
+ emaiLAddress: element.emaiLAddress));
+ }
+ }
+ // pendingFamilyFiles.addAll(tempPendingFamilyFiles.where((element) => !pendingFamilyFiles.any((e) => e.responseId == element.responseId)));
+ pendingFamilyFiles.addAll(tempPendingFamilyFiles.where((element) => !pendingFamilyFiles.any((e) => e.patientId == element.patientId)));
}
+ notifyListeners();
}
},
);
}
+ Future switchFamilyFiles({Function(dynamic)? onSuccess, int? responseID, int? patientID, String? phoneNumber, Function(String)? onError}) async {
+ authVM.phoneNumberController.text = phoneNumber!.startsWith("0") ? phoneNumber.replaceFirst("0", "") : phoneNumber;
+
+ await authVM.checkActivationCode(
+ activationCode: '0000',
+ otpTypeEnum: OTPTypeEnum.sms,
+ onWrongActivationCode: (String? str) {},
+ responseID: responseID,
+ isFormFamilyFile: false,
+ isSwitchUser: true,
+ patientID: patientID,
+ );
+ }
+
+ Future addFamilyFile({required OTPTypeEnum otpTypeEnum}) async {
+ LoaderBottomSheet.showLoader();
+ AuthenticationViewModel authVM = getIt.get();
+ NavigationService navigationService = getIt.get();
+ FamilyFileRequest request =
+ await RequestUtils.getAddFamilyRequest(nationalIDorFile: authVM.nationalIdController.text, mobileNo: authVM.phoneNumberController.text, countryCode: authVM.selectedCountrySignup.countryCode);
+
+ final resultEither = await medicalFileRepo.addFamilyFile(request: request.toJson());
+ resultEither.fold((failure) async => await errorHandlerService.handleError(failure: failure), (apiResponse) async {
+ if (apiResponse.messageStatus == 2) {
+ LoaderBottomSheet.hideLoader();
+ _dialogService.showErrorBottomSheet(
+ message: apiResponse.errorMessage!,
+ onOkPressed: () {
+ navigationService.pop();
+ });
+ } else if (apiResponse.messageStatus == 1) {
+ if (apiResponse.data != null) {
+ request.isPatientExcluded = apiResponse.data["IsPatientExcluded"];
+ request.responseID = apiResponse.data["ReponseID"];
+ LoaderBottomSheet.hideLoader();
+ _dialogService.showExceptionBottomSheet(
+ message: apiResponse.data["Message"],
+ onOkPressed: () {
+ LoaderBottomSheet.showLoader();
+ authVM.sendActivationCode(
+ otpTypeEnum: otpTypeEnum,
+ nationalIdOrFileNumber: request.sharedPatientIdentificationId!,
+ phoneNumber: request.sharedPatientMobileNumber!,
+ isForRegister: false,
+ isExcludedUser: apiResponse.data['IsPatientExcluded'],
+ responseID: apiResponse.data["ReponseID"],
+ isFormFamilyFile: true);
+ },
+ onCancelPressed: () {
+ navigationService.pop();
+ });
+ }
+ }
+ });
+ }
+
+ Future handleFamilyFileRequestOTPVerification() async {
+ LoaderBottomSheet.showLoader();
+ if (!_appState.getIsChildLoggedIn) {
+ await getFamilyFiles(status: 0);
+ await getAllPendingRecordsByResponseId();
+ }
+
+ LoaderBottomSheet.hideLoader();
+ }
+
+ Future removeFileFromFamilyMembers({int? id}) async {
+ NavigationService navigationService = getIt.get();
+ _dialogService.showExceptionBottomSheet(
+ message: "Remove this member?",
+ onOkPressed: () async {
+ LoaderBottomSheet.showLoader();
+ final result = await medicalFileRepo.removeFamilyFile(id: id);
+ result.fold(
+ (failure) async => await errorHandlerService.handleError(failure: failure),
+ (apiResponse) {
+ if (apiResponse.messageStatus == 2) {
+ LoaderBottomSheet.hideLoader();
+ _dialogService.showErrorBottomSheet(
+ message: apiResponse.errorMessage!,
+ onOkPressed: () {
+ navigationService.pop();
+ });
+ } else if (apiResponse.messageStatus == 1) {
+ patientFamilyFiles.removeWhere((element) => element.id == id);
+ LoaderBottomSheet.hideLoader();
+ notifyListeners();
+ navigationService.pop();
+ }
+ },
+ );
+ },
+ onCancelPressed: () {
+ navigationService.pop();
+ });
+ }
+
Future getPatientMedicalReportAppointmentsList({Function(dynamic)? onSuccess, Function(String)? onError}) async {
patientMedicalReportAppointmentHistoryList.clear();
notifyListeners();
@@ -357,8 +566,33 @@ class MedicalFileViewModel extends ChangeNotifier {
);
}
- Future addFamilyFile() async {
- final resultEither = await medicalFileRepo.addFamilyFile(request: {});
- resultEither.fold((failure) async => await errorHandlerService.handleError(failure: failure), (apiResponse) async {});
+ Future acceptRejectFileFromFamilyMembers({int? id, int? status}) async {
+ NavigationService navigationService = getIt.get();
+ LoaderBottomSheet.showLoader();
+ final result = await medicalFileRepo.acceptRejectFamilyFile(id: id, status: status);
+ result.fold(
+ (failure) async => await errorHandlerService.handleError(failure: failure),
+ (apiResponse) {
+ if (apiResponse.messageStatus == 2) {
+ LoaderBottomSheet.hideLoader();
+ _dialogService.showErrorBottomSheet(
+ message: apiResponse.errorMessage!,
+ onOkPressed: () {
+ navigationService.pop();
+ });
+ } else if (apiResponse.messageStatus == 1) {
+ // FamilyFileResponseModelLists moveProfile = pendingFamilyFiles.firstWhere((element) => element.id == patientID);
+ // moveProfile.status = 3;
+ // moveProfile.statusDescription = "Approved";
+ // patientFamilyFiles.add(moveProfile);
+ pendingFamilyFiles.removeWhere((element) => element.id == id);
+ //TODO: Call Api Here To Load Family Members
+ getFamilyFiles(status: 0);
+ getAllPendingRecordsByResponseId();
+ LoaderBottomSheet.hideLoader();
+ onFamilyFileTabChange(0);
+ }
+ },
+ );
}
}
diff --git a/lib/features/medical_file/models/family_file_response_model.dart b/lib/features/medical_file/models/family_file_response_model.dart
index 82fe3d8..f4aa557 100644
--- a/lib/features/medical_file/models/family_file_response_model.dart
+++ b/lib/features/medical_file/models/family_file_response_model.dart
@@ -23,83 +23,90 @@ class FamilyFileResponseModelLists {
String? patientIdenficationNumber;
String? patientName;
String? statusDescription;
+ bool? isSuperUser = false;
+ bool? isRequestFromMySide;
- FamilyFileResponseModelLists({
- this.id,
- this.patientId,
- this.responseId,
- this.relationshipId,
- this.relationship,
- this.relationshipN,
- this.regionId,
- this.familyRegionId,
- this.status,
- this.isActive,
- this.editedOn,
- this.createdOn,
- this.age,
- this.emaiLAddress,
- this.gender,
- this.genderDescription,
- this.genderImage,
- this.mobileNumber,
- this.patientDataVerified,
- this.patientIdenficationNumber,
- this.patientName,
- this.statusDescription,
- });
+ FamilyFileResponseModelLists(
+ {this.id,
+ this.patientId,
+ this.responseId,
+ this.relationshipId,
+ this.relationship,
+ this.relationshipN,
+ this.regionId,
+ this.familyRegionId,
+ this.status,
+ this.isActive,
+ this.editedOn,
+ this.createdOn,
+ this.age,
+ this.emaiLAddress,
+ this.gender,
+ this.genderDescription,
+ this.genderImage,
+ this.mobileNumber,
+ this.patientDataVerified,
+ this.patientIdenficationNumber,
+ this.patientName,
+ this.statusDescription,
+ this.isSuperUser,
+ this.isRequestFromMySide});
factory FamilyFileResponseModelLists.fromRawJson(String str) => FamilyFileResponseModelLists.fromJson(json.decode(str));
String toRawJson() => json.encode(toJson());
factory FamilyFileResponseModelLists.fromJson(Map json) => FamilyFileResponseModelLists(
- id: json["ID"],
- patientId: json["PatientID"],
- responseId: json["ResponseID"],
- relationshipId: json["RelationshipID"],
- relationship: json["Relationship"],
- relationshipN: json["RelationshipN"],
- regionId: json["RegionID"],
- familyRegionId: json["FamilyRegionID"],
- status: json["Status"],
- isActive: json["IsActive"],
- editedOn: json["EditedOn"],
- createdOn: json["CreatedOn"],
- age: json["Age"],
- emaiLAddress: json["EmaiLAddress"],
- gender: json["Gender"],
- genderDescription: json["GenderDescription"],
- genderImage: json["GenderImage"],
- mobileNumber: json["MobileNumber"],
- patientDataVerified: json["PatientDataVerified"],
- patientIdenficationNumber: json["PatientIdenficationNumber"],
- patientName: json["PatientName"],
- statusDescription: json["StatusDescription"],
- );
+ id: json["ID"],
+ patientId: json["PatientID"],
+ responseId: json["ResponseID"],
+ relationshipId: json["RelationshipID"],
+ relationship: json["Relationship"],
+ relationshipN: json["RelationshipN"],
+ regionId: json["RegionID"],
+ familyRegionId: json["FamilyRegionID"],
+ status: json["Status"],
+ isActive: json["IsActive"],
+ editedOn: json["EditedOn"],
+ createdOn: json["CreatedOn"],
+ age: json["Age"],
+ emaiLAddress: json["EmaiLAddress"],
+ gender: json["Gender"],
+ genderDescription: json["GenderDescription"],
+ genderImage: json["GenderImage"],
+ mobileNumber: json["MobileNumber"],
+ patientDataVerified: json["PatientDataVerified"],
+ patientIdenficationNumber: json["PatientIdenficationNumber"],
+ patientName: json["PatientName"],
+ statusDescription: json["StatusDescription"],
+ isSuperUser: json["isSuperUser"] ?? false,
+ isRequestFromMySide: json["isRequestFromMySide"] ?? false,
+ );
Map toJson() => {
- "ID": id,
- "PatientID": patientId,
- "ResponseID": responseId,
- "RelationshipID": relationshipId,
- "Relationship": relationship,
- "RelationshipN": relationshipN,
- "RegionID": regionId,
- "FamilyRegionID": familyRegionId,
- "Status": status,
- "IsActive": isActive,
- "EditedOn": editedOn,
- "CreatedOn": createdOn,
- "Age": age,
- "EmaiLAddress": emaiLAddress,
- "Gender": gender,
- "GenderDescription": genderDescription,
- "GenderImage": genderImage,
- "MobileNumber": mobileNumber,
- "PatientDataVerified": patientDataVerified,
- "PatientIdenficationNumber": patientIdenficationNumber,
- "PatientName": patientName,
- "StatusDescription": statusDescription,
- };
+ "ID": id,
+ "PatientID": patientId,
+ "ResponseID": responseId,
+ "RelationshipID": relationshipId,
+ "Relationship": relationship,
+ "RelationshipN": relationshipN,
+ "RegionID": regionId,
+ "FamilyRegionID": familyRegionId,
+ "Status": status,
+ "IsActive": isActive,
+ "EditedOn": editedOn,
+ "CreatedOn": createdOn,
+ "Age": age,
+ "EmaiLAddress": emaiLAddress,
+ "Gender": gender,
+ "GenderDescription": genderDescription,
+ "GenderImage": genderImage,
+ "MobileNumber": mobileNumber,
+ "PatientDataVerified": patientDataVerified,
+ "PatientIdenficationNumber": patientIdenficationNumber,
+ "PatientName": patientName,
+ "StatusDescription": statusDescription,
+ "isSuperUser": isSuperUser,
+ "isRequestFromMySide": isRequestFromMySide,
+ };
}
diff --git a/lib/features/my_appointments/my_appointments_view_model.dart b/lib/features/my_appointments/my_appointments_view_model.dart
index 926f75d..60fbff2 100644
--- a/lib/features/my_appointments/my_appointments_view_model.dart
+++ b/lib/features/my_appointments/my_appointments_view_model.dart
@@ -92,6 +92,9 @@ class MyAppointmentsViewModel extends ChangeNotifier {
}
setIsAppointmentDataToBeLoaded(bool val) {
+ if (val) {
+ isMyAppointmentsLoading = true;
+ }
isAppointmentDataToBeLoaded = val;
notifyListeners();
}
@@ -112,9 +115,11 @@ class MyAppointmentsViewModel extends ChangeNotifier {
Future getPatientAppointments(bool isActiveAppointment, bool isArrivedAppointments, {Function(dynamic)? onSuccess, Function(String)? onError}) async {
if (!isAppointmentDataToBeLoaded) return;
+ filteredAppointmentList.clear();
patientAppointmentsHistoryList.clear();
patientUpcomingAppointmentsHistoryList.clear();
patientArrivedAppointmentsHistoryList.clear();
+ notifyListeners();
final result = await myAppointmentsRepo.getPatientAppointments(isActiveAppointment: isActiveAppointment, isArrivedAppointments: isArrivedAppointments);
final resultArrived = await myAppointmentsRepo.getPatientAppointments(isActiveAppointment: false, isArrivedAppointments: true);
diff --git a/lib/presentation/home/landing_page.dart b/lib/presentation/home/landing_page.dart
index d235f4d..7de153f 100644
--- a/lib/presentation/home/landing_page.dart
+++ b/lib/presentation/home/landing_page.dart
@@ -19,6 +19,7 @@ import 'package:hmg_patient_app_new/features/book_appointments/book_appointments
import 'package:hmg_patient_app_new/features/habib_wallet/habib_wallet_view_model.dart';
import 'package:hmg_patient_app_new/features/immediate_livecare/immediate_livecare_view_model.dart';
import 'package:hmg_patient_app_new/features/insurance/insurance_view_model.dart';
+import 'package:hmg_patient_app_new/features/medical_file/medical_file_view_model.dart';
import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/patient_appointment_history_response_model.dart';
import 'package:hmg_patient_app_new/features/my_appointments/my_appointments_view_model.dart';
import 'package:hmg_patient_app_new/features/prescriptions/prescriptions_view_model.dart';
@@ -76,6 +77,11 @@ class _LandingPageState extends State {
void initState() {
authVM = context.read();
habibWalletVM = context.read();
+ // myAppointmentsViewModel = context.read();
+ // prescriptionsViewModel = context.read();
+ // insuranceViewModel = context.read();
+ // immediateLiveCareViewModel = context.read();
+
authVM.savePushTokenToAppState();
if (mounted) {
authVM.checkLastLoginStatus(() {
@@ -100,13 +106,12 @@ class _LandingPageState extends State {
@override
Widget build(BuildContext context) {
- appState = getIt.get();
- NavigationService navigationService = getIt.get();
bookAppointmentsViewModel = Provider.of(context, listen: false);
myAppointmentsViewModel = Provider.of(context, listen: false);
prescriptionsViewModel = Provider.of(context, listen: false);
insuranceViewModel = Provider.of(context, listen: false);
immediateLiveCareViewModel = Provider.of(context, listen: false);
+ appState = getIt.get();
return Scaffold(
backgroundColor: AppColors.bgScaffoldColor,
body: SingleChildScrollView(
diff --git a/lib/presentation/medical_file/medical_file_page.dart b/lib/presentation/medical_file/medical_file_page.dart
index 8ff081f..1eff927 100644
--- a/lib/presentation/medical_file/medical_file_page.dart
+++ b/lib/presentation/medical_file/medical_file_page.dart
@@ -17,6 +17,7 @@ import 'package:hmg_patient_app_new/features/book_appointments/models/resp_model
import 'package:hmg_patient_app_new/features/insurance/insurance_view_model.dart';
import 'package:hmg_patient_app_new/features/lab/lab_view_model.dart';
import 'package:hmg_patient_app_new/features/medical_file/medical_file_view_model.dart';
+import 'package:hmg_patient_app_new/features/medical_file/models/family_file_response_model.dart';
import 'package:hmg_patient_app_new/features/medical_file/models/patient_sickleave_response_model.dart';
import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/patient_appointment_history_response_model.dart';
import 'package:hmg_patient_app_new/features/my_appointments/my_appointments_view_model.dart';
@@ -32,6 +33,8 @@ import 'package:hmg_patient_app_new/presentation/insurance/widgets/insurance_upd
import 'package:hmg_patient_app_new/presentation/insurance/widgets/patient_insurance_card.dart';
import 'package:hmg_patient_app_new/presentation/lab/lab_orders_page.dart';
import 'package:hmg_patient_app_new/presentation/lab/lab_result_item_view.dart';
+import 'package:hmg_patient_app_new/presentation/my_family/my_family.dart';
+import 'package:hmg_patient_app_new/services/dialog_service.dart';
import 'package:hmg_patient_app_new/presentation/radiology/radiology_orders_page.dart';
import 'package:hmg_patient_app_new/widgets/appbar/collapsing_list_view.dart';
import 'package:hmg_patient_app_new/presentation/medical_report/medical_reports_page.dart';
@@ -75,6 +78,7 @@ class _MedicalFilePageState extends State {
@override
void initState() {
+ appState = getIt.get();
scheduleMicrotask(() {
if (appState.isAuthenticated) {
labViewModel.initLabProvider();
@@ -94,116 +98,140 @@ class _MedicalFilePageState extends State {
myAppointmentsViewModel = Provider.of(context, listen: false);
medicalFileViewModel = Provider.of(context, listen: false);
bookAppointmentsViewModel = Provider.of(context, listen: false);
- appState = getIt.get();
NavigationService navigationService = getIt.get();
- return Scaffold(
- backgroundColor: AppColors.bgScaffoldColor,
- body: CollapsingListView(
- title: LocaleKeys.medicalFile.tr(context: context),
- isLeading: false,
- child: SingleChildScrollView(
- child: Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- SizedBox(height: 16.h),
- TextInputWidget(
- labelText: LocaleKeys.search.tr(context: context),
- hintText: "Type any record".needTranslation,
- controller: TextEditingController(),
- keyboardType: TextInputType.number,
- isEnable: true,
- prefix: null,
- autoFocus: false,
- isBorderAllowed: false,
- isAllowLeadingIcon: true,
- padding: EdgeInsets.symmetric(vertical: 8.h, horizontal: 8.h),
- leadingIcon: AppAssets.student_card,
- ).paddingSymmetrical(24.h, 0.0),
- SizedBox(height: 16.h),
- Container(
- width: double.infinity,
- decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24),
- child: Padding(
- padding: EdgeInsets.all(16.h),
- child: Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- Row(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- Image.asset(appState.getAuthenticatedUser()?.gender == 1 ? AppAssets.male_img : AppAssets.femaleImg, width: 56.h, height: 56.h),
- SizedBox(width: 8.h),
- Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- "${appState.getAuthenticatedUser()!.firstName} ${appState.getAuthenticatedUser()!.lastName}".toText18(isBold: true),
- SizedBox(height: 4.h),
- Wrap(
- direction: Axis.horizontal,
- spacing: 4.h,
- runSpacing: 4.h,
- children: [
- AppCustomChipWidget(
- icon: AppAssets.file_icon,
- labelText: "${LocaleKeys.fileNo.tr(context: context)}: ${appState.getAuthenticatedUser()!.patientId}",
- ),
- AppCustomChipWidget(
- icon: AppAssets.checkmark_icon,
- labelText: LocaleKeys.verified.tr(context: context),
- iconColor: AppColors.successColor,
- ),
- ],
- ),
- ],
- )
- ],
- ),
- SizedBox(height: 16.h),
- Divider(color: AppColors.dividerColor, height: 1.h),
- SizedBox(height: 16.h),
- Wrap(
- direction: Axis.horizontal,
- spacing: 4.h,
- runSpacing: 4.h,
- children: [
- AppCustomChipWidget(
- labelText: "${appState.getAuthenticatedUser()!.age} Years Old",
- ),
- AppCustomChipWidget(
- icon: AppAssets.blood_icon,
- labelText: "${LocaleKeys.bloodType.tr(context: context)}: ${appState.getUserBloodGroup}",
- iconColor: AppColors.primaryRedColor,
- ),
- ],
- ),
- ],
- ),
- ),
- ).paddingSymmetrical(24.h, 0.0),
- SizedBox(height: 16.h),
- Consumer(builder: (context, medicalFileVM, child) {
- return Column(
+ return CollapsingListView(
+ title: "Medical File".needTranslation,
+ trailing: Row(
+ children: [
+ Wrap(spacing: -15, children: [
+ Utils.buildImgWithAssets(icon: AppAssets.babyGirlImg, width: 32.h, height: 32.h, border: 1.5.h, borderRadius: 50.h),
+ Utils.buildImgWithAssets(icon: AppAssets.femaleImg, width: 32.h, height: 32.h, border: 1.5.h, borderRadius: 50.h),
+ Utils.buildImgWithAssets(icon: AppAssets.male_img, width: 32.h, height: 32.h, border: 1.5.h, borderRadius: 50.h),
+ ]),
+ SizedBox(width: 4.h),
+ Utils.buildSvgWithAssets(icon: AppAssets.arrow_down)
+ ],
+ ).onPress(() {
+ DialogService dialogService = getIt.get();
+ dialogService.showFamilyBottomSheetWithoutH(
+ label: "Who do you want to book for?".needTranslation,
+ message: "This clinic or doctor is only available for the below eligible profiles.".needTranslation,
+ onSwitchPress: (FamilyFileResponseModelLists profile) {
+ medicalFileViewModel.switchFamilyFiles(responseID: profile.responseId, patientID: profile.patientId, phoneNumber: profile.mobileNumber);
+ },
+ profiles: medicalFileViewModel.patientFamilyFiles);
+ }),
+ isLeading: false,
+ child: SingleChildScrollView(
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ SizedBox(height: 16.h),
+ TextInputWidget(
+ labelText: LocaleKeys.search.tr(context: context),
+ hintText: "Type any record".needTranslation,
+ controller: TextEditingController(),
+ keyboardType: TextInputType.number,
+ isEnable: true,
+ prefix: null,
+ autoFocus: false,
+ isBorderAllowed: false,
+ isAllowLeadingIcon: true,
+ padding: EdgeInsets.symmetric(vertical: 8.h, horizontal: 8.h),
+ leadingIcon: AppAssets.student_card,
+ ).paddingSymmetrical(24.h, 0.0),
+ SizedBox(height: 16.h),
+ Container(
+ width: double.infinity,
+ decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24),
+ child: Padding(
+ padding: EdgeInsets.all(16.h),
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
children: [
- CustomTabBar(
- activeTextColor: AppColors.primaryRedColor,
- activeBackgroundColor: AppColors.primaryRedColor.withValues(alpha: .1),
- tabs: [
- CustomTabBarModel(AppAssets.myFilesBottom, LocaleKeys.general.tr(context: context).needTranslation),
- CustomTabBarModel(AppAssets.insurance, LocaleKeys.insurance.tr(context: context)),
- CustomTabBarModel(AppAssets.requests, LocaleKeys.request.tr(context: context).needTranslation),
- CustomTabBarModel(AppAssets.more, "More".needTranslation),
+ Row(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Image.asset(appState.getAuthenticatedUser()?.gender == 1 ? AppAssets.male_img : AppAssets.femaleImg, width: 56.h, height: 56.h),
+ SizedBox(width: 8.h),
+ Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ "${appState.getAuthenticatedUser()!.firstName} ${appState.getAuthenticatedUser()!.lastName}"
+ .toText18(isBold: true, weight: FontWeight.w600, textOverflow: TextOverflow.ellipsis, maxlines: 1),
+ SizedBox(height: 4.h),
+ Wrap(
+ direction: Axis.horizontal,
+ spacing: 4.h,
+ runSpacing: 4.h,
+ children: [
+ AppCustomChipWidget(
+ icon: AppAssets.file_icon,
+ labelText: "${LocaleKeys.fileNo.tr(context: context)}: ${appState.getAuthenticatedUser()!.patientId}",
+ onChipTap: () {
+ navigationService.pushPage(
+ page: FamilyMedicalScreen(
+ profiles: medicalFileViewModel.patientFamilyFiles,
+ onSelect: (FamilyFileResponseModelLists p1) {},
+ ));
+ },
+ ),
+ AppCustomChipWidget(
+ icon: AppAssets.checkmark_icon,
+ labelText: LocaleKeys.verified.tr(context: context),
+ iconColor: AppColors.successColor,
+ ),
+ ],
+ ),
+ ],
+ )
],
- onTabChange: (index) {
- medicalFileVM.onTabChanged(index);
- },
- ).paddingSymmetrical(24.h, 0.0),
- SizedBox(height: 24.h),
- getSelectedTabData(medicalFileVM.selectedTabIndex),
+ ),
+ SizedBox(height: 16.h),
+ Divider(color: AppColors.dividerColor, height: 1.h),
+ SizedBox(height: 16.h),
+ Wrap(
+ direction: Axis.horizontal,
+ spacing: 4.h,
+ runSpacing: 4.h,
+ children: [
+ AppCustomChipWidget(
+ labelText: "${appState.getAuthenticatedUser()!.age} Years Old",
+ ),
+ AppCustomChipWidget(
+ icon: AppAssets.blood_icon,
+ labelText: "${LocaleKeys.bloodType.tr(context: context)}: ${appState.getUserBloodGroup}",
+ iconColor: AppColors.primaryRedColor,
+ ),
+ ],
+ ),
],
- );
- }),
- ],
- ),
+ ),
+ ),
+ ).paddingSymmetrical(24.h, 0.0),
+ SizedBox(height: 16.h),
+ Consumer(builder: (context, medicalFileVM, child) {
+ return Column(
+ children: [
+ CustomTabBar(
+ activeTextColor: AppColors.primaryRedColor,
+ activeBackgroundColor: AppColors.primaryRedColor.withValues(alpha: .1),
+ tabs: [
+ CustomTabBarModel(AppAssets.myFilesBottom, LocaleKeys.general.tr(context: context).needTranslation),
+ CustomTabBarModel(AppAssets.insurance, LocaleKeys.insurance.tr(context: context)),
+ CustomTabBarModel(AppAssets.requests, LocaleKeys.request.tr(context: context).needTranslation),
+ CustomTabBarModel(AppAssets.more, "More".needTranslation),
+ ],
+ onTabChange: (index) {
+ medicalFileVM.onTabChanged(index);
+ },
+ ).paddingSymmetrical(24.h, 0.0),
+ SizedBox(height: 24.h),
+ getSelectedTabData(medicalFileVM.selectedTabIndex),
+ ],
+ );
+ }),
+ ],
),
),
);
diff --git a/lib/presentation/my_family/my_family.dart b/lib/presentation/my_family/my_family.dart
index 25f5f3c..8a04cd5 100644
--- a/lib/presentation/my_family/my_family.dart
+++ b/lib/presentation/my_family/my_family.dart
@@ -1,23 +1,29 @@
+import 'dart:convert';
+
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/app_state.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/validation_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/features/authentication/authentication_view_model.dart';
+import 'package:hmg_patient_app_new/features/medical_file/medical_file_view_model.dart';
import 'package:hmg_patient_app_new/features/medical_file/models/family_file_response_model.dart';
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
import 'package:hmg_patient_app_new/presentation/my_family/widget/family_cards.dart';
+import 'package:hmg_patient_app_new/services/dialog_service.dart';
import 'package:hmg_patient_app_new/theme/colors.dart';
-import 'package:hmg_patient_app_new/widgets/appbar/app_bar_widget.dart';
+import 'package:hmg_patient_app_new/widgets/appbar/collapsing_list_view.dart';
import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart';
import 'package:hmg_patient_app_new/widgets/common_bottom_sheet.dart';
import 'package:hmg_patient_app_new/widgets/custom_tab_bar.dart';
import 'package:hmg_patient_app_new/widgets/dropdown/country_dropdown_widget.dart';
import 'package:hmg_patient_app_new/widgets/input_widget.dart';
+import 'package:provider/provider.dart';
class FamilyMedicalScreen extends StatefulWidget {
final List profiles;
@@ -34,161 +40,95 @@ class FamilyMedicalScreen extends StatefulWidget {
}
class _FamilyMedicalScreenState extends State {
- List tabs = [CustomTabBarModel("", LocaleKeys.medicalFile.tr()), CustomTabBarModel("", LocaleKeys.request.tr())];
+ MedicalFileViewModel? medicalVM;
+
+ @override
+ void initState() {
+ super.initState();
+ medicalVM = context.read();
+ }
@override
Widget build(BuildContext context) {
- return Scaffold(
- backgroundColor: AppColors.scaffoldBgColor,
- appBar: CustomAppBar(
- onBackPressed: () {
- Navigator.of(context).pop();
- },
- onLanguageChanged: (lang) {},
- hideLogoAndLang: true,
- ),
- body: SingleChildScrollView(
- child: Column(
- mainAxisSize: MainAxisSize.min,
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- LocaleKeys.myMedicalFile.tr().toText26(color: AppColors.textColor, weight: FontWeight.w600, letterSpacing: -2),
- SizedBox(height: 25.h),
- CustomTabBar(
- tabs: tabs,
- onTabChange: (int index) {},
- ),
- SizedBox(height: 25.h),
- FamilyCards(profiles: widget.profiles, onSelect: widget.onSelect, isShowDetails: true),
- SizedBox(height: 20.h),
- ],
- ),
- ).paddingSymmetrical(20, 0),
- bottomSheet: Container(
- decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
- color: AppColors.whiteColor,
- customBorder: BorderRadius.only(topLeft: Radius.circular(24), topRight: Radius.circular(24)),
- ),
- padding: EdgeInsets.symmetric(vertical: 10.h, horizontal: 20.h),
- child: CustomButton(
- text: "Add a new family member",
- onPressed: () {
- showModelSheet();
+ AppState appState = getIt.get();
+
+ return CollapsingListView(
+ title: "My Medical File".needTranslation,
+ bottomChild: appState.getAuthenticatedUser()!.isParentUser!
+ ? Container(
+ decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
+ color: AppColors.whiteColor,
+ customBorder: BorderRadius.only(topLeft: Radius.circular(24), topRight: Radius.circular(24)),
+ ),
+ padding: EdgeInsets.symmetric(vertical: 10.h, horizontal: 20.h),
+ child: CustomButton(
+ text: "Add a new family member".needTranslation,
+ onPressed: () {
+ DialogService dialogService = getIt.get();
+ dialogService.showAddFamilyFileSheet(
+ label: "Add Family Member".needTranslation,
+ message: "Please fill the below field to add a new family member to your profile".needTranslation,
+ onVerificationPress: () {
+ medicalVM!.addFamilyFile(otpTypeEnum: OTPTypeEnum.sms);
+ });
+ },
+ icon: AppAssets.add_icon,
+ height: 56.h,
+ fontSize: 16,
+ borderRadius: 12.h,
+ fontWeight: FontWeight.w500))
+ : SizedBox(),
+ child: Column(
+ mainAxisSize: MainAxisSize.min,
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ CustomTabBar(
+ activeBackgroundColor: AppColors.secondaryLightRedColor,
+ activeTextColor: AppColors.primaryRedColor,
+ tabs: appState.isChildLoggedIn
+ ? [CustomTabBarModel(null, LocaleKeys.medicalFile.tr())]
+ : [CustomTabBarModel(null, LocaleKeys.medicalFile.tr()), CustomTabBarModel(null, LocaleKeys.request.tr())],
+ onTabChange: (index) {
+ medicalVM!.onFamilyFileTabChange(index);
},
- icon: AppAssets.add_icon,
- height: 56.h,
- fontWeight: FontWeight.w600,
- )),
+ ),
+ SizedBox(height: 25.h),
+ Selector(selector: (_, model) => model.getSelectedFamilyFileTabIndex, builder: (context, selectedIndex, child) => getFamilyTabs(index: selectedIndex)),
+ SizedBox(height: 20.h),
+ ],
+ ).paddingSymmetrical(20, 0),
);
}
- Future showModelSheet() async {
- AuthenticationViewModel authVm = getIt.get();
- return await showCommonBottomSheetWithoutHeight(context,
- title: "Add Family Member",
- child: Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- mainAxisAlignment: MainAxisAlignment.start,
- children: [
- "Please fill the below field to add a new family member to your profile".toText16(color: AppColors.textColor, weight: FontWeight.w500),
- SizedBox(height: 20.h),
- Container(
- decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(24)),
- padding: EdgeInsets.symmetric(horizontal: 16.h, vertical: 8.h),
- child: Column(
- children: [
- CustomCountryDropdown(
- countryList: CountryEnum.values,
- onCountryChange: authVm.onCountryChange,
- ).paddingOnly(top: 8.h, bottom: 16.h),
- Divider(
- height: 1.h,
- color: AppColors.spacerLineColor,
- ),
- TextInputWidget(
- labelText: LocaleKeys.nationalIdNumber.tr(),
- hintText: "xxxxxxxxx",
- controller: authVm.nationalIdController,
- // focusNode: _nationalIdFocusNode,
- isEnable: true,
- prefix: null,
- isAllowRadius: true,
- isBorderAllowed: false,
- isAllowLeadingIcon: true,
- autoFocus: true,
- keyboardType: TextInputType.number,
- padding: EdgeInsets.symmetric(vertical: 8.h),
- leadingIcon: AppAssets.student_card,
- ).paddingOnly(top: 8.h, bottom: 8.h),
- Divider(
- height: 1.h,
- color: AppColors.spacerLineColor,
- ),
- TextInputWidget(
- labelText: LocaleKeys.phoneNumber.tr(),
- hintText: "574345434",
- controller: authVm.phoneNumberController,
- isEnable: true,
- prefix: authVm.selectedCountrySignup.countryCode,
- isAllowRadius: true,
- isBorderAllowed: false,
- isAllowLeadingIcon: true,
- autoFocus: true,
- keyboardType: TextInputType.number,
- padding: EdgeInsets.symmetric(vertical: 8.h),
- leadingIcon: AppAssets.smart_phone,
- ).paddingOnly(top: 8.h, bottom: 4),
-
- //TextInputWidget(
- // labelText: widget.isForEmail ? LocaleKeys.email.tr() : LocaleKeys.phoneNumber.tr(),
- // hintText: widget.isForEmail ? "demo@gmail.com" : "5xxxxxxxx",
- // controller: widget.textController!,
- // focusNode: _textFieldFocusNode,
- // autoFocus: widget.autoFocus,
- // padding: EdgeInsets.all(8.h),
- // keyboardType: widget.isForEmail ? TextInputType.emailAddress : TextInputType.number,
- // onChange: (value) {
- // if (widget.onChange != null) {
- // widget.onChange!(value);
- // }
- // },
- // onCountryChange: (value) {
- // if (widget.onCountryChange != null) {
- // widget.onCountryChange!(value);
- // }
- // },
- // isEnable: true,
- // isReadOnly: widget.isFromSavedLogin,
- // prefix: widget.isForEmail ? null : widget.countryCode,
- // isBorderAllowed: false,
- // isAllowLeadingIcon: true,
- // fontSize: 13.h,
- // isCountryDropDown: widget.isEnableCountryDropdown,
- // leadingIcon: widget.isForEmail ? AppAssets.email : AppAssets.smart_phone,
- // )
- ],
- ),
- ),
- SizedBox(height: 20.h),
- CustomButton(
- text: "Verify the member",
- onPressed: () {
- FocusScope.of(context).unfocus();
- if (ValidationUtils.isValidatedIdAndPhoneWithCountryValidation(
- nationalId: authVm.nationalIdController.text,
- selectedCountry: authVm.selectedCountrySignup,
- phoneNumber: authVm.phoneNumberController.text,
- onOkPress: () {
- Navigator.of(context).pop();
- },
- )) {}
- },
- icon: AppAssets.add_icon,
- height: 56.h,
- fontWeight: FontWeight.w600),
- SizedBox(height: 20.h),
- ],
- ),
- callBackFunc: () {});
+ Widget getFamilyTabs({required int index}) {
+ switch (index) {
+ case 0:
+ return FamilyCards(
+ profiles: medicalVM!.patientFamilyFiles,
+ onSelect: (FamilyFileResponseModelLists profile) {
+ medicalVM!.switchFamilyFiles(responseID: profile.responseId, patientID: profile.patientId, phoneNumber: profile.mobileNumber);
+ },
+ onRemove: (FamilyFileResponseModelLists profile) {
+ medicalVM!.removeFileFromFamilyMembers(id: profile.id);
+ },
+ isLeftAligned: true,
+ isShowDetails: true,
+ isShowRemoveButton: true,
+ );
+ case 1:
+ return FamilyCards(
+ profiles: medicalVM!.pendingFamilyFiles,
+ isRequestDesign: true,
+ onSelect: (FamilyFileResponseModelLists profile) {
+ medicalVM!.acceptRejectFileFromFamilyMembers(id: profile.id, status: 3);
+ },
+ onRemove: (FamilyFileResponseModelLists profile) {
+ medicalVM!.acceptRejectFileFromFamilyMembers(id: profile.id, status: 4);
+ },
+ isShowDetails: true,
+ );
+ default:
+ return SizedBox.shrink();
+ }
}
}
diff --git a/lib/presentation/my_family/widget/family_cards.dart b/lib/presentation/my_family/widget/family_cards.dart
index 306692b..eeb82e5 100644
--- a/lib/presentation/my_family/widget/family_cards.dart
+++ b/lib/presentation/my_family/widget/family_cards.dart
@@ -10,6 +10,8 @@ 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/medical_file/models/family_file_response_model.dart';
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
+import 'package:hmg_patient_app_new/services/dialog_service.dart';
+import 'package:hmg_patient_app_new/services/navigation_service.dart';
import 'package:hmg_patient_app_new/theme/colors.dart';
import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart';
import 'package:hmg_patient_app_new/widgets/chip/custom_chip_widget.dart';
@@ -17,10 +19,23 @@ import 'package:hmg_patient_app_new/widgets/chip/custom_chip_widget.dart';
class FamilyCards extends StatefulWidget {
final List profiles;
final Function(FamilyFileResponseModelLists) onSelect;
+ final Function(FamilyFileResponseModelLists) onRemove;
final bool isShowDetails;
final bool isBottomSheet;
+ final bool isRequestDesign;
+ final bool isLeftAligned;
+ final bool isShowRemoveButton;
- const FamilyCards({super.key, required this.profiles, required this.onSelect, this.isShowDetails = false, this.isBottomSheet = false});
+ const FamilyCards(
+ {super.key,
+ required this.profiles,
+ required this.onSelect,
+ required this.onRemove,
+ this.isShowDetails = false,
+ this.isBottomSheet = false,
+ this.isRequestDesign = false,
+ this.isLeftAligned = false,
+ this.isShowRemoveButton = false});
@override
State createState() => _FamilyCardsState();
@@ -31,79 +46,294 @@ class _FamilyCardsState extends State {
@override
Widget build(BuildContext context) {
- return GridView.builder(
+ DialogService dialogService = getIt.get();
+ if (widget.isRequestDesign) {
+ return Column(
+ children: [
+ Row(
+ children: [
+ Utils.buildSvgWithAssets(icon: AppAssets.alertSquare),
+ SizedBox(width: 8.h),
+ "Who can view my medical file ?".needTranslation.toText14(color: AppColors.textColor, isUnderLine: true, weight: FontWeight.w500).onPress(() {
+ dialogService.showFamilyBottomSheetWithoutHWithChild(
+ label: "Manage Family".needTranslation,
+ message: "",
+ child: manageFamily(),
+ onOkPressed: () {},
+ );
+ }),
+ SizedBox(width: 4.h),
+ Utils.buildSvgWithAssets(icon: AppAssets.arrowRight),
+ ],
+ ),
+ SizedBox(height: 24.h),
+ ListView.builder(
+ shrinkWrap: true,
+ physics: NeverScrollableScrollPhysics(),
+ padding: EdgeInsets.zero,
+ itemCount: widget.profiles.where((profile) => profile.isRequestFromMySide ?? false).length,
+ itemBuilder: (context, index) {
+ final mySideProfiles = widget.profiles.where((profile) => profile.isRequestFromMySide ?? false).toList();
+ FamilyFileResponseModelLists profile = mySideProfiles[index];
+ return Container(
+ margin: EdgeInsets.only(bottom: 12.h),
+ padding: EdgeInsets.symmetric(vertical: 15.h, horizontal: 15.h),
+ decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24),
+ child: Opacity(
+ opacity: 1.0,
+ child: Column(
+ mainAxisSize: MainAxisSize.min,
+ crossAxisAlignment: CrossAxisAlignment.start,
+ mainAxisAlignment: MainAxisAlignment.start,
+ children: [
+ CustomChipWidget(
+ height: 30.h,
+ chipType: ChipTypeEnum.alert,
+ backgroundColor: profile.status == FamilyFileEnum.pending.toInt
+ ? AppColors.alertLightColor.withValues(alpha: 0.20)
+ : profile.status == FamilyFileEnum.rejected.toInt
+ ? AppColors.primaryRedColor.withValues(alpha: 0.20)
+ : profile.status == FamilyFileEnum.active.toInt
+ ? AppColors.lightGreenColor
+ : AppColors.lightGrayBGColor,
+ chipText: profile.statusDescription ?? "N/A",
+ iconAsset: null,
+ isShowBorder: false,
+ borderRadius: 8.h,
+ textColor: profile.status == FamilyFileEnum.pending.toInt
+ ? AppColors.alertLightColor
+ : profile.status == FamilyFileEnum.rejected.toInt
+ ? AppColors.primaryRedColor
+ : profile.status == FamilyFileEnum.active.toInt
+ ? AppColors.textGreenColor
+ : AppColors.alertColor),
+ SizedBox(height: 8.h),
+ Wrap(alignment: WrapAlignment.start, crossAxisAlignment: WrapCrossAlignment.start, runAlignment: WrapAlignment.start, spacing: 0.h, children: [
+ (profile.patientName ?? "").toText14(isBold: false, isCenter: false, maxlines: 1, weight: FontWeight.w600),
+ (getStatusTextByRequest(FamilyFileEnum.values.firstWhere((e) => e.toInt == profile.status), profile.isRequestFromMySide ?? false))
+ .toText12(isBold: false, isCenter: false, maxLine: 1, fontWeight: FontWeight.w500, color: AppColors.greyTextColor),
+ ]),
+ SizedBox(height: 8.h),
+ CustomChipWidget(
+ height: 30.h,
+ chipType: ChipTypeEnum.alert,
+ backgroundColor: AppColors.lightGrayBGColor,
+ chipText: "Medical File: ${profile.responseId ?? "N/A"}",
+ iconAsset: null,
+ isShowBorder: false,
+ borderRadius: 8.h,
+ textColor: AppColors.textColor),
+ ],
+ ),
+ ),
+ );
+ },
+ ),
+ SizedBox(height: 20.h),
+ ],
+ );
+ } else {
+ return GridView.builder(
+ shrinkWrap: true,
+ physics: NeverScrollableScrollPhysics(),
+ itemCount: widget.profiles.length,
+ gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
+ crossAxisCount: 2,
+ crossAxisSpacing: 10.h,
+ mainAxisSpacing: 10.h,
+ childAspectRatio: widget.isShowDetails ? 0.56.h : 0.65.h,
+ ),
+ padding: EdgeInsets.only(bottom: 20.h),
+ itemBuilder: (context, index) {
+ final profile = widget.profiles[index];
+ final isActive = (profile.responseId == appState.getAuthenticatedUser()?.patientId);
+ final isParentUser = appState.getAuthenticatedUser()?.isParentUser ?? false;
+ final canSwitch = isParentUser || (!isParentUser && profile.responseId == appState.getSuperUserID);
+ return Container(
+ padding: EdgeInsets.symmetric(vertical: 15.h, horizontal: 15.h),
+ decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24),
+ child: Opacity(
+ opacity: isActive || profile.status == FamilyFileEnum.pending.toInt || !canSwitch ? 0.4 : 1.0, // Fade all content if active
+ child: Stack(
+ children: [
+ Column(
+ mainAxisSize: MainAxisSize.min,
+ children: [
+ Utils.buildImgWithAssets(
+ icon: profile.gender == null
+ ? AppAssets.dummy_user
+ : profile.gender == 1
+ ? ((profile.age ?? 0) < 7 ? AppAssets.babyBoyImg : AppAssets.male_img)
+ : (profile.age! < 7 ? AppAssets.babyGirlImg : AppAssets.femaleImg),
+ width: 80.h,
+ height: 78.h),
+ SizedBox(height: 8.h),
+ (profile.patientName ?? "Unknown").toText14(isBold: false, isCenter: true, maxlines: 1, weight: FontWeight.w600),
+ SizedBox(height: 8.h),
+ CustomChipWidget(
+ chipType: ChipTypeEnum.alert,
+ backgroundColor: AppColors.lightGrayBGColor,
+ chipText: "Relation:${profile.relationship ?? "N/A"}",
+ iconAsset: AppAssets.heart,
+ isShowBorder: false,
+ borderRadius: 8.h,
+ textColor: AppColors.textColor),
+ widget.isShowDetails ? SizedBox(height: 4.h) : SizedBox(),
+ widget.isShowDetails
+ ? CustomChipWidget(
+ chipType: ChipTypeEnum.alert,
+ backgroundColor: AppColors.lightGrayBGColor,
+ chipText: "Age:${profile.age ?? "N/A"} Years",
+ isShowBorder: false,
+ borderRadius: 8.h,
+ textColor: AppColors.textColor,
+ )
+ : SizedBox(),
+ widget.isShowDetails
+ ? SizedBox(height: 8.h)
+ : SizedBox(
+ height: 4.h,
+ ),
+ Spacer(),
+ CustomButton(
+ height: 40.h,
+ onPressed: () {
+ if (canSwitch) widget.onSelect(profile);
+ },
+ text: isActive ? "Active".needTranslation : "Switch".needTranslation,
+ backgroundColor: isActive || !canSwitch ? Colors.grey.shade200 : AppColors.secondaryLightRedColor,
+ borderColor: isActive || !canSwitch ? Colors.grey.shade200 : AppColors.secondaryLightRedColor,
+ textColor: isActive || !canSwitch ? AppColors.greyTextColor : AppColors.primaryRedColor,
+ fontSize: 13.h,
+ icon: isActive ? AppAssets.activeCheck : AppAssets.switch_user,
+ iconColor: isActive || !canSwitch ? (isActive ? null : AppColors.greyTextColor) : AppColors.primaryRedColor,
+ padding: EdgeInsets.symmetric(vertical: 0, horizontal: 0),
+ ).paddingOnly(top: 0, bottom: 0),
+ ],
+ ),
+ if (widget.isShowRemoveButton) ...[
+ Positioned(
+ top: 0,
+ right: 0,
+ child: Utils.buildSvgWithAssets(icon: AppAssets.deleteIcon).onPress(() {
+ if (!isActive) widget.onRemove(profile);
+ }),
+ ),
+ ],
+ ],
+ ),
+ ),
+ );
+ },
+ );
+ }
+ }
+
+ Widget manageFamily() {
+ NavigationService navigationService = getIt();
+ return ListView.builder(
shrinkWrap: true,
- physics: const NeverScrollableScrollPhysics(),
- itemCount: widget.profiles.length,
- gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
- crossAxisCount: 2,
- crossAxisSpacing: 10.h,
- mainAxisSpacing: 10.h,
- childAspectRatio: widget.isShowDetails ? 0.56.h : 0.74.h,
- ),
+ physics: NeverScrollableScrollPhysics(),
+ padding: EdgeInsetsGeometry.zero,
+ itemCount: widget.profiles.where((profile) => !(profile.isRequestFromMySide ?? false)).length,
itemBuilder: (context, index) {
- final profile = widget.profiles[index];
- final isActive = (profile.responseId == appState.getAuthenticatedUser()?.patientId);
+ final otherProfiles = widget.profiles.where((profile) => !(profile.isRequestFromMySide ?? false)).toList();
+ FamilyFileResponseModelLists profile = otherProfiles[index];
return Container(
+ margin: EdgeInsets.only(bottom: 12.h),
padding: EdgeInsets.symmetric(vertical: 15.h, horizontal: 15.h),
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24),
child: Opacity(
- opacity: isActive ? 0.4 : 1.0, // Fade all content if active
+ opacity: 1.0,
child: Column(
mainAxisSize: MainAxisSize.min,
+ crossAxisAlignment: CrossAxisAlignment.start,
+ mainAxisAlignment: MainAxisAlignment.start,
children: [
- SizedBox(height: 5.h),
- Utils.buildImgWithAssets(
- icon: profile.gender == 1 ? ((profile.age ?? 0) < 7 ? AppAssets.babyBoyImg : AppAssets.male_img) : (profile.age! < 7 ? AppAssets.babyGirlImg : AppAssets.femaleImg),
- width: 80.h,
- height: 78.h),
+ CustomChipWidget(
+ height: 30.h,
+ chipType: ChipTypeEnum.alert,
+ backgroundColor: profile.status == FamilyFileEnum.pending.toInt
+ ? AppColors.alertLightColor.withValues(alpha: 0.20)
+ : profile.status == FamilyFileEnum.rejected.toInt
+ ? AppColors.primaryRedColor.withValues(alpha: 0.20)
+ : profile.status == FamilyFileEnum.active.toInt
+ ? AppColors.lightGreenColor
+ : AppColors.lightGrayBGColor,
+ chipText: profile.statusDescription ?? "N/A",
+ iconAsset: null,
+ isShowBorder: false,
+ borderRadius: 8.h,
+ textColor: profile.status == FamilyFileEnum.pending.toInt
+ ? AppColors.alertLightColor
+ : profile.status == FamilyFileEnum.rejected.toInt
+ ? AppColors.primaryRedColor
+ : profile.status == FamilyFileEnum.active.toInt
+ ? AppColors.textGreenColor
+ : AppColors.alertColor,
+ ),
+ SizedBox(height: 8.h),
+ Wrap(
+ alignment: WrapAlignment.start,
+ children: [
+ (profile.patientName ?? "").toText14(isBold: false, isCenter: true, maxlines: 1, weight: FontWeight.w600),
+ (getStatusTextByRequest(FamilyFileEnum.values.firstWhere((e) => e.toInt == profile.status), profile.isRequestFromMySide ?? false)).toText14(
+ isBold: false,
+ isCenter: true,
+ maxlines: 1,
+ weight: FontWeight.w500,
+ color: AppColors.greyTextColor,
+ ),
+ ],
+ ),
SizedBox(height: 8.h),
- (profile.patientName ?? "Unknown").toText16(isBold: false, isCenter: true, maxlines: 1, weight: FontWeight.w600),
- SizedBox(height: 4.h),
CustomChipWidget(
- chipType: ChipTypeEnum.alert,
- backgroundColor: AppColors.lightGrayBGColor,
- chipText: "Relation: ${profile.relationship ?? "N/A"}",
- iconAsset: AppAssets.heart,
- isShowBorder: false,
- borderRadius: 8.h,
- textColor: AppColors.textColor),
- widget.isShowDetails ? SizedBox(height: 4.h) : SizedBox(),
- widget.isShowDetails
- ? CustomChipWidget(
- chipType: ChipTypeEnum.alert,
- backgroundColor: AppColors.lightGrayBGColor,
- chipText: "Age: ${profile.age ?? "N/A"} Years",
- isShowBorder: false,
- borderRadius: 8.h,
- textColor: AppColors.textColor,
- )
- : SizedBox(),
- widget.isShowDetails ? SizedBox(height: 8.h) : SizedBox(),
- Spacer(),
- if (isActive)
- CustomButton(
- height: 40.h,
- onPressed: () {},
- text: LocaleKeys.active.tr(),
- backgroundColor: Colors.grey.shade200,
- borderColor: Colors.grey.shade200,
- textColor: AppColors.greyTextColor,
- fontSize: 13.h,
- ).paddingOnly(top: 0, bottom: 0)
- else
- CustomButton(
- height: 40.h,
- onPressed: () => widget.onSelect(profile),
- text: LocaleKeys.select.tr(),
- backgroundColor: AppColors.secondaryLightRedColor,
- borderColor: AppColors.secondaryLightRedColor,
- textColor: AppColors.primaryRedColor,
- fontSize: 13.h,
- icon: widget.isBottomSheet ? null : AppAssets.heart,
- iconColor: AppColors.primaryRedColor,
- padding: EdgeInsets.symmetric(vertical: 0, horizontal: 0),
- ).paddingOnly(top: 0, bottom: 0),
+ height: 30.h,
+ chipType: ChipTypeEnum.alert,
+ backgroundColor: AppColors.lightGrayBGColor,
+ chipText: "Medical File: ${profile.patientId ?? "N/A".needTranslation}",
+ iconAsset: null,
+ isShowBorder: false,
+ borderRadius: 8.h,
+ textColor: AppColors.textColor,
+ ),
+ SizedBox(height: 16.h),
+ Row(
+ children: [
+ profile.status == FamilyFileEnum.active.toInt
+ ? SizedBox()
+ : Expanded(
+ child: CustomButton(
+ height: 40.h,
+ text: LocaleKeys.confirm.tr(),
+ onPressed: () {
+ navigationService.pop();
+ widget.onSelect(profile);
+ },
+ backgroundColor: AppColors.lightGreenButtonColor,
+ borderColor: AppColors.lightGreenButtonColor,
+ textColor: AppColors.textGreenColor,
+ icon: null,
+ ),
+ ),
+ profile.status == FamilyFileEnum.active.toInt ? SizedBox() : SizedBox(width: 8.h),
+ Expanded(
+ child: CustomButton(
+ height: 40.h,
+ text: profile.status == FamilyFileEnum.active.toInt ? LocaleKeys.removeMember.tr() : LocaleKeys.cancel.tr(),
+ onPressed: () {
+ navigationService.pop();
+ widget.onRemove(profile);
+ },
+ backgroundColor: AppColors.secondaryLightRedColor,
+ borderColor: AppColors.secondaryLightRedColor,
+ textColor: AppColors.primaryRedColor,
+ icon: null,
+ iconColor: AppColors.primaryRedColor,
+ ),
+ ),
+ ],
+ ),
],
),
),
@@ -111,4 +341,31 @@ class _FamilyCardsState extends State {
},
);
}
+
+ String getStatusTextByRequest(FamilyFileEnum status, bool isRequestFromMySide) {
+ switch (status) {
+ case FamilyFileEnum.active:
+ if (isRequestFromMySide) {
+ return "${status.displayName} your request to be your family member".needTranslation;
+ } else {
+ return "can view your file".needTranslation;
+ }
+ case FamilyFileEnum.pending:
+ if (isRequestFromMySide) {
+ return "has a request ${status.displayName} to be your family member".needTranslation;
+ } else {
+ return "wants to add you as their family member".needTranslation;
+ }
+ case FamilyFileEnum.rejected:
+ if (isRequestFromMySide) {
+ return "${status.displayName} your request to be your family member".needTranslation;
+ } else {
+ return "${status.displayName} your family member request".needTranslation;
+ }
+ case FamilyFileEnum.inactive:
+ return "Inactive".needTranslation;
+ default:
+ return "N/A".needTranslation;
+ }
+ }
}
diff --git a/lib/presentation/my_family/widget/my_family_sheet.dart b/lib/presentation/my_family/widget/my_family_sheet.dart
index da822b1..d469ab2 100644
--- a/lib/presentation/my_family/widget/my_family_sheet.dart
+++ b/lib/presentation/my_family/widget/my_family_sheet.dart
@@ -1,27 +1,31 @@
import 'package:flutter/material.dart';
+import 'package:hmg_patient_app_new/core/dependencies.dart';
import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
import 'package:hmg_patient_app_new/features/medical_file/models/family_file_response_model.dart';
import 'package:hmg_patient_app_new/presentation/my_family/widget/family_cards.dart';
+import 'package:hmg_patient_app_new/services/navigation_service.dart';
import 'package:hmg_patient_app_new/theme/colors.dart';
import 'package:hmg_patient_app_new/widgets/common_bottom_sheet.dart';
class MyFamilySheet {
static Future show(BuildContext context, List familyLists, Function(FamilyFileResponseModelLists) onSelect) async {
- return await showCommonBottomSheetWithoutHeight(
+ NavigationService navigationService = getIt();
+ return showCommonBottomSheetWithoutHeight(
context,
titleWidget: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
- 'Please select a profile'.toText21(isBold: true),
- 'switch from the below list of medical file'.toText16(weight: FontWeight.w100, color: AppColors.greyTextColor),
+ 'Please select a profile'.needTranslation.toText21(isBold: true),
+ 'switch from the below list of medical file'.needTranslation.toText16(weight: FontWeight.w100, color: AppColors.greyTextColor),
],
),
child: FamilyCards(
profiles: familyLists,
onSelect: (profile) {
- Navigator.of(context).pop(); // Close the bottom sheet
- onSelect(profile); // Call the onSelect callback
+ navigationService.pop();
+ onSelect(profile);
},
+ onRemove: (profile) {},
isBottomSheet: true),
callBackFunc: () {},
);
diff --git a/lib/presentation/profile_settings/profile_settings.dart b/lib/presentation/profile_settings/profile_settings.dart
index e5ec389..efc02ad 100644
--- a/lib/presentation/profile_settings/profile_settings.dart
+++ b/lib/presentation/profile_settings/profile_settings.dart
@@ -1,3 +1,6 @@
+import 'dart:convert';
+import 'dart:developer';
+
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:flutter_swiper_view/flutter_swiper_view.dart';
@@ -5,16 +8,22 @@ 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_state.dart';
import 'package:hmg_patient_app_new/core/utils/date_util.dart';
+import 'package:hmg_patient_app_new/core/app_state.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/utils.dart';
import 'package:hmg_patient_app_new/extensions/int_extensions.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/habib_wallet/habib_wallet_view_model.dart';
import 'package:hmg_patient_app_new/features/insurance/insurance_view_model.dart';
+import 'package:hmg_patient_app_new/features/medical_file/medical_file_view_model.dart';
+import 'package:hmg_patient_app_new/features/medical_file/models/family_file_response_model.dart';
import 'package:hmg_patient_app_new/features/profile_settings/profile_settings_view_model.dart';
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
import 'package:hmg_patient_app_new/presentation/habib_wallet/habib_wallet_page.dart';
import 'package:hmg_patient_app_new/presentation/habib_wallet/recharge_wallet_page.dart';
+import 'package:hmg_patient_app_new/services/dialog_service.dart';
import 'package:hmg_patient_app_new/widgets/appbar/collapsing_list_view.dart';
import 'package:hmg_patient_app_new/theme/colors.dart';
import 'package:hmg_patient_app_new/widgets/app_language_change.dart';
@@ -50,8 +59,6 @@ class _ProfileSettingsState extends State {
int length = 3;
final SwiperController _controller = SwiperController();
- int _index = 0;
-
@override
Widget build(BuildContext context) {
return CollapsingListView(
@@ -61,27 +68,41 @@ class _ProfileSettingsState extends State {
child: SingleChildScrollView(
padding: EdgeInsets.only(top: 24, bottom: 24),
physics: NeverScrollableScrollPhysics(),
- child: Consumer(
- builder: (context, model, child) {
+ child: Consumer2(
+ builder: (context, profileVm, medicalVm, child) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Swiper(
- itemCount: length,
+ itemCount: medicalVm.patientFamilyFiles.length,
layout: SwiperLayout.STACK,
loop: true,
itemWidth: MediaQuery.of(context).size.width - 42,
indicatorLayout: PageIndicatorLayout.COLOR,
axisDirection: AxisDirection.right,
controller: _controller,
- itemHeight: 210 + 16,
+ itemHeight: 200.h,
pagination: const SwiperPagination(
alignment: Alignment.bottomCenter,
margin: EdgeInsets.only(top: 210 + 8 + 24),
builder: DotSwiperPaginationBuilder(color: Color(0xffD9D9D9), activeColor: AppColors.blackBgColor),
),
itemBuilder: (BuildContext context, int index) {
- return FamilyCardWidget(isRootUser: true).paddingOnly(right: 16);
+ return FamilyCardWidget(
+ profile: medicalVm.patientFamilyFiles[index],
+ onAddFamilyMemberPress: () {
+ DialogService dialogService = getIt.get();
+ dialogService.showAddFamilyFileSheet(
+ label: "Add Family Member".needTranslation,
+ message: "Please fill the below field to add a new family member to your profile".needTranslation,
+ onVerificationPress: () {
+ medicalVm.addFamilyFile(otpTypeEnum: OTPTypeEnum.sms);
+ });
+ },
+ onFamilySwitchPress: (FamilyFileResponseModelLists profile) {
+ medicalVm.switchFamilyFiles(responseID: profile.responseId, patientID: profile.patientId, phoneNumber: profile.mobileNumber);
+ },
+ ).paddingOnly(right: 16);
},
),
GridView(
@@ -230,115 +251,300 @@ class _ProfileSettingsState extends State {
}
class FamilyCardWidget extends StatelessWidget {
- FamilyCardWidget({this.isRootUser = true, Key? key}) : super(key: key);
-
- bool isRootUser;
late AppState appState;
+ final Function() onAddFamilyMemberPress;
+ final Function(FamilyFileResponseModelLists member) onFamilySwitchPress;
+ final FamilyFileResponseModelLists profile;
+
+ FamilyCardWidget({super.key, required this.onAddFamilyMemberPress, required this.profile, required this.onFamilySwitchPress(FamilyFileResponseModelLists member)});
@override
Widget build(BuildContext context) {
- appState = getIt.get();
+ AppState appState = getIt.get();
+ final isActive = (profile.responseId == appState.getAuthenticatedUser()?.patientId);
+ final isParentUser = appState.getAuthenticatedUser()?.isParentUser ?? false;
+ final canSwitch = isParentUser || (!isParentUser && profile.responseId == appState.getSuperUserID);
return Container(
- decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
- color: AppColors.whiteColor,
- borderRadius: 20.h,
- hasShadow: true,
- ),
+ decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 20.h, hasShadow: true),
child: Column(
children: [
Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
spacing: 8.h,
children: [
Row(
crossAxisAlignment: CrossAxisAlignment.start,
spacing: 8.h,
children: [
- Image.asset(appState.getAuthenticatedUser()?.gender == 1 ? AppAssets.male_img : AppAssets.femaleImg, width: 56.h, height: 56.h),
+ Image.asset(profile.gender == 1 ? AppAssets.male_img : AppAssets.femaleImg, width: 56.h, height: 56.h),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
spacing: 0.h,
mainAxisSize: MainAxisSize.min,
children: [
- "${appState.getAuthenticatedUser()!.firstName} ${appState.getAuthenticatedUser()!.lastName}"
- .toText18(isBold: true, weight: FontWeight.w600, textOverflow: TextOverflow.ellipsis, maxlines: 1),
+ "${profile.patientName}".toText18(isBold: true, weight: FontWeight.w600, textOverflow: TextOverflow.ellipsis, maxlines: 1),
AppCustomChipWidget(
icon: AppAssets.file_icon,
- labelText: "${LocaleKeys.fileNo.tr(context: context)}: ${appState.getAuthenticatedUser()!.patientId}",
+ labelText: "${LocaleKeys.fileNo.tr(context: context)}: ${profile.responseId}",
iconSize: 12,
),
],
).expanded,
Icon(Icons.qr_code, size: 56)
],
- ).expanded,
+ ),
+ SizedBox(height: 4.h),
SizedBox(
- width: double.infinity,
child: Wrap(
alignment: WrapAlignment.start,
- spacing: 8.h,
+ spacing: 4.h,
+ runSpacing: 4.h,
children: [
- AppCustomChipWidget(labelText: "${appState.getAuthenticatedUser()!.age} Years Old"),
+ AppCustomChipWidget(labelText: "${profile.age} Years Old".needTranslation),
AppCustomChipWidget(
- icon: AppAssets.blood_icon,
- labelText: "${LocaleKeys.bloodType.tr(context: context)}: ${appState.getUserBloodGroup}",
- iconColor: AppColors.primaryRedColor,
- ),
- Consumer(builder: (context, insuranceVM, child) {
- return AppCustomChipWidget(
- icon: insuranceVM.isInsuranceLoading
- ? AppAssets.cancel_circle_icon
- : (DateTime.now().isAfter(
- DateUtil.convertStringToDate(insuranceVM.patientInsuranceList.first.cardValidTo),
- ))
- ? AppAssets.cancel_circle_icon
- : AppAssets.insurance_active_icon,
- labelText: insuranceVM.isInsuranceLoading
- ? "Insurance"
- : (DateTime.now().isAfter(
- DateUtil.convertStringToDate(insuranceVM.patientInsuranceList.first.cardValidTo),
- )
- ? "Insurance Expired".needTranslation
- : "Insurance Active".needTranslation),
- iconColor: insuranceVM.isInsuranceLoading
- ? AppColors.primaryRedColor
- : (DateTime.now().isAfter(
- DateUtil.convertStringToDate(insuranceVM.patientInsuranceList.first.cardValidTo),
- ))
- ? AppColors.primaryRedColor
- : AppColors.successColor,
- iconSize: 14,
- backgroundColor: insuranceVM.isInsuranceLoading
- ? AppColors.primaryRedColor
- : (DateTime.now().isAfter(
- DateUtil.convertStringToDate(insuranceVM.patientInsuranceList.first.cardValidTo),
- ))
- ? AppColors.primaryRedColor.withValues(alpha: 0.15)
- : AppColors.successColor.withValues(alpha: 0.15),
- ).toShimmer2(isShow: insuranceVM.isInsuranceLoading);
- }),
+ icon: AppAssets.blood_icon,
+ labelPadding: EdgeInsetsDirectional.only(start: -6.h, end: 8.h),
+ labelText: "Blood: ${appState.getAuthenticatedUser()!.bloodGroup ?? "."}",
+ iconColor: AppColors.primaryRedColor),
+ Selector(
+ selector: (context, insuranceVM) => (
+ isEmpty: insuranceVM.patientInsuranceList.isEmpty,
+ patientID: insuranceVM.patientInsuranceList.isNotEmpty ? insuranceVM.patientInsuranceList.first.patientID : null,
+ isLoading: insuranceVM.isInsuranceLoading,
+ cardValidTo: insuranceVM.patientInsuranceList.isNotEmpty ? insuranceVM.patientInsuranceList.first.cardValidTo : null
+ ),
+ builder: (context, data, child) {
+ if (data.isEmpty) {
+ return const SizedBox();
+ } else if (profile.responseId != data.patientID) {
+ return SizedBox();
+ }
+
+ final isLoading = data.isLoading;
+ final isExpired = !isLoading && DateTime.now().isAfter(DateUtil.convertStringToDate(data.cardValidTo));
+
+ final String icon;
+ final String labelText;
+ final Color iconColor;
+ final Color backgroundColor;
+
+ if (isLoading) {
+ icon = AppAssets.cancel_circle_icon;
+ labelText = "Insurance";
+ iconColor = AppColors.primaryRedColor;
+ backgroundColor = AppColors.primaryRedColor;
+ } else if (isExpired) {
+ icon = AppAssets.cancel_circle_icon;
+ labelText = "Insurance Expired".needTranslation;
+ iconColor = AppColors.primaryRedColor;
+ backgroundColor = AppColors.primaryRedColor.withValues(alpha: 0.15);
+ } else {
+ icon = AppAssets.insurance_active_icon;
+ labelText = "Insurance Active".needTranslation;
+ iconColor = AppColors.successColor;
+ backgroundColor = AppColors.successColor.withValues(alpha: 0.15);
+ }
+
+ return AppCustomChipWidget(
+ icon: icon,
+ labelText: labelText,
+ iconColor: iconColor,
+ iconSize: 12,
+ backgroundColor: backgroundColor,
+ labelPadding: EdgeInsetsDirectional.only(start: -6.h, end: 8.h),
+ // padding: EdgeInsets.zero,
+ ).toShimmer2(isShow: isLoading);
+ },
+ )
+
+ // Consumer(builder: (context, insuranceVM, child) {
+ // if (insuranceVM.patientInsuranceList.isEmpty) {
+ // return const SizedBox();
+ // } else if (profile.responseId != insuranceVM.patientInsuranceList.first.patientID) {
+ // return SizedBox();
+ // }
+ //
+ // final isLoading = insuranceVM.isInsuranceLoading;
+ // final isExpired = !isLoading && DateTime.now().isAfter(DateUtil.convertStringToDate(insuranceVM.patientInsuranceList.first.cardValidTo));
+ //
+ // final String icon;
+ // final String labelText;
+ // final Color iconColor;
+ // final Color backgroundColor;
+ //
+ // if (isLoading) {
+ // icon = AppAssets.cancel_circle_icon;
+ // labelText = "Insurance";
+ // iconColor = AppColors.primaryRedColor;
+ // backgroundColor = AppColors.primaryRedColor;
+ // } else if (isExpired) {
+ // icon = AppAssets.cancel_circle_icon;
+ // labelText = "Insurance Expired".needTranslation;
+ // iconColor = AppColors.primaryRedColor;
+ // backgroundColor = AppColors.primaryRedColor.withValues(alpha: 0.15);
+ // } else {
+ // icon = AppAssets.insurance_active_icon;
+ // labelText = "Insurance Active".needTranslation;
+ // iconColor = AppColors.successColor;
+ // backgroundColor = AppColors.successColor.withValues(alpha: 0.15);
+ // }
+ //
+ // return AppCustomChipWidget(
+ // icon: icon,
+ // labelText: labelText,
+ // iconColor: iconColor,
+ // iconSize: 12,
+ // backgroundColor: backgroundColor,
+ // // padding: EdgeInsets.zero,
+ // ).toShimmer2(isShow: isLoading);
+ // })
+
+ // Consumer(builder: (context, insuranceVM, child) {
+ // return insuranceVM.patientInsuranceList. isNotEmpty ? AppCustomChipWidget(
+ // icon: insuranceVM.isInsuranceLoading
+ // ? AppAssets.cancel_circle_icon
+ // : (DateTime.now().isAfter(
+ // DateUtil.convertStringToDate(insuranceVM.patientInsuranceList.first.cardValidTo),
+ // ))
+ // ? AppAssets.cancel_circle_icon
+ // : AppAssets.insurance_active_icon,
+ // labelText: insuranceVM.isInsuranceLoading
+ // ? "Insurance"
+ // : (DateTime.now().isAfter(
+ // DateUtil.convertStringToDate(insuranceVM.patientInsuranceList.first.cardValidTo),
+ // )
+ // ? "Insurance Expired".needTranslation
+ // : "Insurance Active".needTranslation),
+ // iconColor: insuranceVM.isInsuranceLoading
+ // ? AppColors.primaryRedColor
+ // : (DateTime.now().isAfter(
+ // DateUtil.convertStringToDate(insuranceVM.patientInsuranceList.first.cardValidTo),
+ // ))
+ // ? AppColors.primaryRedColor
+ // : AppColors.successColor,
+ // iconSize: 14,
+ // backgroundColor: insuranceVM.isInsuranceLoading
+ // ? AppColors.primaryRedColor
+ // : (DateTime.now().isAfter(
+ // DateUtil.convertStringToDate(insuranceVM.patientInsuranceList.first.cardValidTo),
+ // ))
+ // ? AppColors.primaryRedColor.withValues(alpha: 0.15)
+ // : AppColors.successColor.withValues(alpha: 0.15),
+ // ).toShimmer2(isShow: insuranceVM.isInsuranceLoading) : SizedBox();
+ // }),
],
),
),
],
- ).paddingOnly(top: 16, right: 16, left: 16, bottom: 12).expanded,
+ ).paddingOnly(top: 16.h, right: 16.h, left: 16.h, bottom: 12.h).expanded,
1.divider,
- //TODO: Add family file switch logic here
- isRootUser
- ? CustomButton(icon: AppAssets.add_family, text: "Add a new family member".needTranslation, height: 40.h, fontSize: 14, onPressed: () {})
- .paddingOnly(top: 12, right: 16, left: 16, bottom: 16)
- : CustomButton(
- icon: AppAssets.add_family,
- backgroundColor: AppColors.secondaryLightRedColor,
- borderColor: AppColors.secondaryLightRedColor,
- textColor: AppColors.primaryRedColor,
- iconColor: AppColors.primaryRedColor,
- text: "Switch to this medical file".needTranslation,
- height: 40.h,
- fontSize: 14,
- onPressed: () {})
- .paddingOnly(top: 12, right: 16, left: 16, bottom: 16),
+ _buildActionButton(appState),
+
+ // if (appState.getAuthenticatedUser()!.isParentUser ?? false) ...[
+ // if (member!.responseId != appState.getAuthenticatedUser()!.patientId) ...[
+ // CustomButton(
+ // icon: AppAssets.switch_user,
+ // text: "Switch Family File".needTranslation,
+ // onPressed: () {
+ // onFamilySwitchPress(member!);
+ // },
+ // ).paddingOnly(top: 12, right: 16, left: 16, bottom: 16),
+ // ] else
+ // ...[
+ // CustomButton(
+ // icon: AppAssets.add_family,
+ // text: "Add a new family member".needTranslation,
+ // onPressed: () {
+ // onAddFamilyMemberPress();
+ // },
+ // ).paddingOnly(top: 12, right: 16, left: 16, bottom: 16),
+ // ]
+ // ] else
+ // ...[
+ // if (appState.getSuperUserID != null && appState.getSuperUserID == member!.responseId) ...[
+ // CustomButton(
+ // icon: AppAssets.switch_user,
+ // text: "Switch Back To Family File".needTranslation,
+ // onPressed: () {
+ // onFamilySwitchPress(member!);
+ // },
+ // ).paddingOnly(top: 12, right: 16, left: 16, bottom: 16),
+ // ] else
+ // ...[
+ // CustomButton(
+ // icon: AppAssets.switch_user,
+ // text: "Disabled".needTranslation,
+ // backgroundColor: Colors.grey.shade200,
+ // borderColor: Colors.grey.shade200,
+ // textColor: AppColors.greyTextColor,
+ // onPressed: () {},
+ // iconColor: AppColors.greyTextColor,
+ // ).paddingOnly(top: 12, right: 16, left: 16, bottom: 16),
+ // ]
+ // ]
],
),
);
}
+
+ Widget _buildActionButton(AppState appState) {
+ final isParentUser = appState.getAuthenticatedUser()?.isParentUser ?? false;
+ final int? currentUserId = appState.getAuthenticatedUser()?.patientId;
+ final int? superUserId = appState.getSuperUserID;
+
+ if (isParentUser) {
+ return _buildParentUserButton(currentUserId);
+ } else {
+ return _buildNonParentUserButton(superUserId);
+ }
+ }
+
+ Widget _buildParentUserButton(int? currentUserId) {
+ final canSwitch = profile.responseId != currentUserId;
+
+ return CustomButton(
+ icon: canSwitch ? AppAssets.switch_user : AppAssets.add_family,
+ text: canSwitch ? "Switch Family File".needTranslation : "Add a new family member".needTranslation,
+ onPressed: canSwitch ? () => onFamilySwitchPress(profile) : onAddFamilyMemberPress,
+ backgroundColor: canSwitch ? AppColors.secondaryLightRedColor : AppColors.primaryRedColor,
+ borderColor: canSwitch ? AppColors.secondaryLightRedColor : AppColors.primaryRedColor,
+ textColor: canSwitch ? AppColors.primaryRedColor : AppColors.whiteColor,
+ iconColor: canSwitch ? AppColors.primaryRedColor : AppColors.whiteColor,
+ height: 40.h,
+ fontSize: 14,
+ ).paddingOnly(top: 12, right: 16, left: 16, bottom: 16);
+ }
+
+ Widget _buildNonParentUserButton(int? superUserId) {
+ final canSwitchBack = superUserId != null && superUserId == profile.responseId;
+
+ return CustomButton(
+ icon: AppAssets.switch_user,
+ text: canSwitchBack ? "Switch Back To Family File".needTranslation : "Switch".needTranslation,
+ backgroundColor: canSwitchBack ? AppColors.primaryRedColor : Colors.grey.shade200,
+ borderColor: canSwitchBack ? AppColors.primaryRedColor : Colors.grey.shade200,
+ textColor: canSwitchBack ? AppColors.whiteColor : AppColors.greyTextColor,
+ iconColor: canSwitchBack ? AppColors.whiteColor : AppColors.greyTextColor,
+ onPressed: canSwitchBack ? () => onFamilySwitchPress(profile) : () {},
+ height: 40.h,
+ fontSize: 14,
+ ).paddingOnly(top: 12, right: 16, left: 16, bottom: 16);
+ }
+
+// //TODO: Add family file switch logic here
+// isRootUser
+// ? CustomButton(icon: AppAssets.add_family, text: "Add a new family member".needTranslation, height: 40.h, fontSize: 14, onPressed: () {})
+// .paddingOnly(top: 12, right: 16, left: 16, bottom: 16)
+// : CustomButton(
+// icon: AppAssets.add_family,
+// backgroundColor: AppColors.secondaryLightRedColor,
+// borderColor: AppColors.secondaryLightRedColor,
+// textColor: AppColors.primaryRedColor,
+// iconColor: AppColors.primaryRedColor,
+// text: "Switch to this medical file".needTranslation,
+// height: 40.h,
+// fontSize: 14,
+// onPressed: () {})
+// .paddingOnly(top: 12, right: 16, left: 16, bottom: 16),
+//
}
diff --git a/lib/routes/app_routes.dart b/lib/routes/app_routes.dart
index 67bf208..5a93216 100644
--- a/lib/routes/app_routes.dart
+++ b/lib/routes/app_routes.dart
@@ -4,6 +4,7 @@ import 'package:hmg_patient_app_new/presentation/authentication/register.dart';
import 'package:hmg_patient_app_new/presentation/authentication/register_step2.dart';
import 'package:hmg_patient_app_new/presentation/home/landing_page.dart';
import 'package:hmg_patient_app_new/presentation/home/navigation_screen.dart';
+import 'package:hmg_patient_app_new/presentation/medical_file/medical_file_page.dart';
import 'package:hmg_patient_app_new/splashPage.dart';
class AppRoutes {
@@ -12,6 +13,7 @@ class AppRoutes {
static const String register = '/register';
static const String registerStepTwo = '/registerStepTwo';
static const String landingScreen = '/landingScreen';
+ static const String medicalFilePage = '/medicalFilePage';
static Map get routes => {
initialRoute: (context) => SplashPage(),
@@ -19,5 +21,6 @@ class AppRoutes {
landingScreen: (context) => LandingNavigation(),
register: (context) => RegisterNew(),
registerStepTwo: (context) => RegisterNewStep2(),
+ medicalFilePage: (context) => MedicalFilePage(),
};
}
diff --git a/lib/services/dialog_service.dart b/lib/services/dialog_service.dart
index 6ee0ddc..7003a31 100644
--- a/lib/services/dialog_service.dart
+++ b/lib/services/dialog_service.dart
@@ -4,12 +4,15 @@ import 'package:hmg_patient_app_new/core/app_assets.dart';
import 'package:hmg_patient_app_new/core/utils/size_utils.dart';
import 'package:hmg_patient_app_new/extensions/route_extensions.dart';
import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
+import 'package:hmg_patient_app_new/features/medical_file/models/family_file_response_model.dart';
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
+import 'package:hmg_patient_app_new/presentation/my_family/widget/family_cards.dart';
import 'package:hmg_patient_app_new/services/navigation_service.dart';
import 'package:hmg_patient_app_new/theme/colors.dart';
import 'package:hmg_patient_app_new/widgets/bottomsheet/exception_bottom_sheet.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/family_files/family_file_add_widget.dart';
abstract class DialogService {
Future showErrorBottomSheet({String title = "", required String message, Function()? onOkPressed, Function()? onCancelPressed});
@@ -18,7 +21,14 @@ abstract class DialogService {
Future showCommonBottomSheetWithoutH({String? label, required String message, required Function() onOkPressed, Function()? onCancelPressed});
+ Future showFamilyBottomSheetWithoutH(
+ {String? label, required String message, required Function(FamilyFileResponseModelLists response) onSwitchPress, required List profiles});
+
+ Future showFamilyBottomSheetWithoutHWithChild({String? label, required String message, Widget? child, required Function() onOkPressed, Function()? onCancelPressed});
+
Future showPhoneNumberPickerSheet({String? label, String? message, required Function() onSMSPress, required Function() onWhatsappPress});
+
+ Future showAddFamilyFileSheet({String? label, String? message, required Function() onVerificationPress});
// TODO : Need to be Fixed showPhoneNumberPickerSheet ( From Login ADn Signup Bottom Sheet Move Here
}
@@ -93,6 +103,36 @@ class DialogServiceImp implements DialogService {
title: label ?? "", child: exceptionBottomSheetWidget(context: context, message: message, onOkPressed: onOkPressed, onCancelPressed: onCancelPressed), callBackFunc: () {});
}
+ @override
+ Future showFamilyBottomSheetWithoutH(
+ {String? label, required String message, required Function(FamilyFileResponseModelLists response) onSwitchPress, required List profiles}) async {
+ final context = navigationService.navigatorKey.currentContext;
+ if (context == null) return;
+ showCommonBottomSheetWithoutHeight(context,
+ title: label ?? "",
+ child: FamilyCards(
+ profiles: profiles,
+ onSelect: (FamilyFileResponseModelLists profile) {
+ onSwitchPress(profile);
+ },
+ onRemove: (FamilyFileResponseModelLists profile) {},
+ isShowDetails: false,
+ ),
+ callBackFunc: () {});
+ }
+
+ @override
+ Future showFamilyBottomSheetWithoutHWithChild({String? label, required String message, Widget? child, required Function() onOkPressed, Function()? onCancelPressed}) async {
+ final context = navigationService.navigatorKey.currentContext;
+ if (context == null) return;
+ showCommonBottomSheetWithoutHeight(
+ context,
+ title: label ?? "",
+ child: child ?? SizedBox(),
+ callBackFunc: () {},
+ );
+ }
+
@override
Future showPhoneNumberPickerSheet({String? label, String? message, required Function() onSMSPress, required Function() onWhatsappPress}) async {
final context = navigationService.navigatorKey.currentContext;
@@ -100,6 +140,18 @@ class DialogServiceImp implements DialogService {
showCommonBottomSheetWithoutHeight(context,
title: label ?? "", child: showPhoneNumberPickerWidget(context: context, message: message, onSMSPress: onSMSPress, onWhatsappPress: onWhatsappPress), callBackFunc: () {});
}
+
+ @override
+ Future showAddFamilyFileSheet({String? label, String? message, required Function() onVerificationPress}) async {
+ final context = navigationService.navigatorKey.currentContext;
+ if (context == null) return;
+ showCommonBottomSheetWithoutHeight(context,
+ title: label ?? "",
+ child: FamilyFileAddWidget(() {
+ onVerificationPress();
+ }, message ?? ""),
+ callBackFunc: () {});
+ }
}
Widget exceptionBottomSheetWidget({required BuildContext context, required String message, required Function() onOkPressed, Function()? onCancelPressed}) {
@@ -216,3 +268,12 @@ Widget showPhoneNumberPickerWidget({required BuildContext context, String? messa
// );
});
}
+
+// Widget familyMemberAddWidget() {
+// AuthenticationViewModel authVm = getIt.get();
+// return showCommonBottomSheetWithoutHeight(context,
+// title: "Add Family Member".needTranslation,
+// useSafeArea: true,
+// child:
+// callBackFunc: () {});
+// }
diff --git a/lib/services/navigation_service.dart b/lib/services/navigation_service.dart
index bfdedef..b5c5e03 100644
--- a/lib/services/navigation_service.dart
+++ b/lib/services/navigation_service.dart
@@ -34,9 +34,9 @@ class NavigationService {
navigatorKey.currentState?.pushReplacementNamed(routeName);
}
- Future pushToOtpScreen({required String phoneNumber, required Function(int code) checkActivationCode, required Function(String phoneNumber) onResendOTPPressed}) {
+ Future pushToOtpScreen({required String phoneNumber, required Function(int code) checkActivationCode, required Function(String phoneNumber) onResendOTPPressed, bool isFormFamilyFile = false}) {
return navigatorKey.currentState!.push(
- MaterialPageRoute(builder: (_) => OTPVerificationScreen(phoneNumber: phoneNumber, checkActivationCode: checkActivationCode, onResendOTPPressed: onResendOTPPressed)),
+ MaterialPageRoute(builder: (_) => OTPVerificationScreen(phoneNumber: phoneNumber, checkActivationCode: checkActivationCode, onResendOTPPressed: onResendOTPPressed, isFormFamilyFile : isFormFamilyFile)),
);
}
diff --git a/lib/widgets/appbar/collapsing_list_view.dart b/lib/widgets/appbar/collapsing_list_view.dart
index 951732b..2687944 100644
--- a/lib/widgets/appbar/collapsing_list_view.dart
+++ b/lib/widgets/appbar/collapsing_list_view.dart
@@ -22,10 +22,11 @@ class CollapsingListView extends StatelessWidget {
VoidCallback? logout;
VoidCallback? history;
Widget? bottomChild;
+ Widget? trailing;
bool isClose;
bool isLeading;
- CollapsingListView({required this.title, this.child, this.search, this.isClose = false, this.bottomChild, this.report, this.logout, this.history, this.isLeading = true});
+ CollapsingListView({required this.title, this.child, this.search, this.isClose = false, this.bottomChild, this.report, this.logout, this.history, this.isLeading = true, this.trailing});
@override
Widget build(BuildContext context) {
@@ -97,7 +98,8 @@ class CollapsingListView extends StatelessWidget {
if (logout != null) actionButton(context, t, title: "Logout".needTranslation, icon: AppAssets.logout).onPress(logout!),
if (report != null) actionButton(context, t, title: "Report".needTranslation, icon: AppAssets.report_icon).onPress(report!),
if (history != null) actionButton(context, t, title: "History".needTranslation, icon: AppAssets.insurance_history_icon).onPress(history!),
- 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),
+ if (trailing != null) trailing!,
],
)),
),
diff --git a/lib/widgets/buttons/custom_button.dart b/lib/widgets/buttons/custom_button.dart
index a4bec4c..05ec83f 100644
--- a/lib/widgets/buttons/custom_button.dart
+++ b/lib/widgets/buttons/custom_button.dart
@@ -23,28 +23,30 @@ class CustomButton extends StatelessWidget {
final double? width;
final double iconSize;
final TextOverflow? textOverflow;
+ final BorderSide? borderSide;
- CustomButton({
- Key? key,
- required this.text,
- required this.onPressed,
- this.backgroundColor = const Color(0xFFED1C2B),
- this.borderColor = const Color(0xFFED1C2B),
- this.textColor = Colors.white,
- this.borderRadius = 12,
- this.borderWidth = 2,
- this.padding = const EdgeInsets.fromLTRB(8, 10, 8, 10),
- this.fontSize = 16,
- this.fontFamily,
- this.fontWeight = FontWeight.w500,
- this.isDisabled = false,
- this.icon,
- this.iconColor = Colors.white,
- this.height = 56,
- this.width,
- this.iconSize = 24,
- this.textOverflow,
- }) : super(key: key);
+ CustomButton(
+ {Key? key,
+ required this.text,
+ required this.onPressed,
+ this.backgroundColor = const Color(0xFFED1C2B),
+ this.borderColor = const Color(0xFFED1C2B),
+ this.textColor = Colors.white,
+ this.borderRadius = 12,
+ this.borderWidth = 2,
+ this.padding = const EdgeInsets.fromLTRB(8, 10, 8, 10),
+ this.fontSize = 16,
+ this.fontFamily,
+ this.fontWeight = FontWeight.w500,
+ this.isDisabled = false,
+ this.icon,
+ this.iconColor = Colors.white,
+ this.height = 56,
+ this.width,
+ this.iconSize = 24,
+ this.textOverflow,
+ this.borderSide})
+ : super(key: key);
@override
Widget build(BuildContext context) {
@@ -57,17 +59,15 @@ class CustomButton extends StatelessWidget {
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: isDisabled ? Colors.transparent : backgroundColor,
borderRadius: borderRadius,
- side: BorderSide(
- width: borderWidth.h,
- color: isDisabled ? borderColor.withOpacity(0.5) : borderColor,
- )),
+ customBorder: BorderRadius.circular(borderRadius),
+ side: borderSide ?? BorderSide(width: borderWidth.h, color: isDisabled ? borderColor.withValues(alpha: 0.5) : borderColor)),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
if (icon != null)
Padding(
- padding: const EdgeInsets.only(right: 8.0, left: 8.0),
+ padding: EdgeInsets.only(right: 8.h, left: 8.h),
child: Utils.buildSvgWithAssets(icon: icon!, iconColor: iconColor, isDisabled: isDisabled, width: iconSize, height: iconSize),
),
Padding(
@@ -85,17 +85,6 @@ class CustomButton extends StatelessWidget {
),
],
),
- )
-
- // .toSmoothContainer(
- // smoothness: 1,
- // side: BorderSide(width: borderWidth, color: backgroundColor),
- // borderRadius: BorderRadius.circular(borderRadius * 1.2),
- // foregroundDecoration: BoxDecoration(
- // color: isDisabled ? backgroundColor.withOpacity(0.5) : Colors.transparent,
- // borderRadius: BorderRadius.circular(borderRadius),
- // ),
- // ),
- );
+ ));
}
}
diff --git a/lib/widgets/chip/app_custom_chip_widget.dart b/lib/widgets/chip/app_custom_chip_widget.dart
index 783a83f..2cfd5ce 100644
--- a/lib/widgets/chip/app_custom_chip_widget.dart
+++ b/lib/widgets/chip/app_custom_chip_widget.dart
@@ -24,7 +24,8 @@ class AppCustomChipWidget extends StatelessWidget {
this.deleteIconColor = AppColors.textColor,
this.deleteIconHasColor = false,
this.padding = EdgeInsets.zero,
- this.labelPadding ,
+ this.onChipTap,
+ this.labelPadding,
});
final String? labelText;
@@ -42,57 +43,61 @@ class AppCustomChipWidget extends StatelessWidget {
final OutlinedBorder? shape;
final EdgeInsets? padding;
final EdgeInsetsDirectional? labelPadding;
+ final void Function()? onChipTap;
@override
Widget build(BuildContext context) {
- return ChipTheme(
- data: ChipThemeData(
- padding: EdgeInsets.all(0.0),
- shape: SmoothRectangleBorder(
- side: BorderSide(
- width: 10.0,
- color: Colors.transparent, // Crucially, set color to transparent
- style: BorderStyle.none,
+ return GestureDetector(
+ onTap: onChipTap,
+ child: ChipTheme(
+ data: ChipThemeData(
+ padding: EdgeInsets.all(0.0),
+ shape: SmoothRectangleBorder(
+ side: BorderSide(
+ width: 10.0,
+ color: Colors.transparent, // Crucially, set color to transparent
+ style: BorderStyle.none,
+ ),
+ borderRadius: BorderRadius.circular(8.0), // Apply a border radius of 16.0
),
- borderRadius: BorderRadius.circular(8.0), // Apply a border radius of 16.0
),
- ),
- child: icon.isNotEmpty
- ? Chip(
- avatar: icon.isNotEmpty ? Utils.buildSvgWithAssets(icon: icon, width: iconSize.h, height: iconSize.h, iconColor: iconHasColor ? iconColor : null, fit: BoxFit.contain) : SizedBox.shrink(),
- label: richText ?? labelText!.toText10(weight: FontWeight.w500, letterSpacing: 0, color: textColor),
- // padding: EdgeInsets.all(0.0),
- padding: padding,
- materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
- labelPadding: labelPadding??EdgeInsetsDirectional.only(start: 0.h, end: deleteIcon?.isNotEmpty == true ? 2.h : 8.h),
- backgroundColor: backgroundColor,
- shape: shape ??
- SmoothRectangleBorder(
- borderRadius: BorderRadius.circular(8 ?? 0),
- smoothness: 10,
- side: BorderSide(color: AppColors.transparent, width: 1.5),
- ),
- deleteIcon: deleteIcon?.isNotEmpty == true
- ? Utils.buildSvgWithAssets(icon: deleteIcon!, width: deleteIconSize!.width!.h, height: deleteIconSize!.height.h, iconColor: deleteIconHasColor ? deleteIconColor : null)
- : null,
- onDeleted: deleteIcon?.isNotEmpty == true ? () {} : null,
- )
- : Chip(
- materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
- label: richText ?? labelText!.toText10(weight: FontWeight.w500, letterSpacing: 0, color: textColor),
- padding: EdgeInsets.all(0.0),
- backgroundColor: backgroundColor,
- shape: shape ?? SmoothRectangleBorder(
- borderRadius: BorderRadius.circular(8 ?? 0),
- smoothness: 10,
- side: BorderSide(color: AppColors.transparent, width: 1.5),
+ child: icon.isNotEmpty
+ ? Chip(
+ avatar: icon.isNotEmpty ? Utils.buildSvgWithAssets(icon: icon, width: iconSize.h, height: iconSize.h, iconColor: iconHasColor ? iconColor : null, fit: BoxFit.contain) : SizedBox.shrink(),
+ label: richText ?? labelText!.toText10(weight: FontWeight.w500, letterSpacing: 0, color: textColor),
+ padding: padding,
+ materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
+ labelPadding: labelPadding ?? EdgeInsetsDirectional.only(start: 0.h, end: deleteIcon?.isNotEmpty == true ? 2.h : 8.h),
+ backgroundColor: backgroundColor,
+ shape: shape ??
+ SmoothRectangleBorder(
+ borderRadius: BorderRadius.circular(8 ?? 0),
+ smoothness: 10,
+ side: BorderSide(color: AppColors.transparent, width: 1.5),
+ ),
+ deleteIcon: deleteIcon?.isNotEmpty == true
+ ? Utils.buildSvgWithAssets(icon: deleteIcon!, width: deleteIconSize!.width!.h, height: deleteIconSize!.height.h, iconColor: deleteIconHasColor ? deleteIconColor : null)
+ : null,
+ onDeleted: deleteIcon?.isNotEmpty == true ? () {} : null,
+ )
+ : Chip(
+ materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
+ label: richText ?? labelText!.toText10(weight: FontWeight.w500, letterSpacing: 0, color: textColor),
+ padding: EdgeInsets.all(0.0),
+ backgroundColor: backgroundColor,
+ shape: shape ??
+ SmoothRectangleBorder(
+ borderRadius: BorderRadius.circular(8 ?? 0),
+ smoothness: 10,
+ side: BorderSide(color: AppColors.transparent, width: 1.5),
+ ),
+ labelPadding: EdgeInsetsDirectional.only(start: 8.h, end: deleteIcon?.isNotEmpty == true ? -2.h : 8.h),
+ deleteIcon: deleteIcon?.isNotEmpty == true
+ ? Utils.buildSvgWithAssets(icon: deleteIcon!, width: deleteIconSize!.width.h, height: deleteIconSize!.height.h, iconColor: deleteIconHasColor ? deleteIconColor : null)
+ : null,
+ onDeleted: deleteIcon?.isNotEmpty == true ? () {} : null,
),
- labelPadding: EdgeInsetsDirectional.only(start: 8.h, end: deleteIcon?.isNotEmpty == true ? -2.h : 8.h),
- deleteIcon: deleteIcon?.isNotEmpty == true
- ? Utils.buildSvgWithAssets(icon: deleteIcon!, width: deleteIconSize!.width.h, height: deleteIconSize!.height.h, iconColor: deleteIconHasColor ? deleteIconColor : null)
- : null,
- onDeleted: deleteIcon?.isNotEmpty == true ? () {} : null,
- ),
+ ),
);
}
}
diff --git a/lib/widgets/chip/custom_chip_widget.dart b/lib/widgets/chip/custom_chip_widget.dart
index 1d0b5ef..5dee4f0 100644
--- a/lib/widgets/chip/custom_chip_widget.dart
+++ b/lib/widgets/chip/custom_chip_widget.dart
@@ -17,6 +17,7 @@ class CustomChipWidget extends StatelessWidget {
final Color? textColor;
final Color? borderColor;
final bool isShowBorder;
+ final double? height;
const CustomChipWidget({
super.key,
@@ -31,6 +32,7 @@ class CustomChipWidget extends StatelessWidget {
this.textColor,
this.borderColor,
this.isShowBorder = false,
+ this.height,
});
@override
@@ -39,6 +41,7 @@ class CustomChipWidget extends StatelessWidget {
final hasOnTap = onTap != null || hasIcon;
return Container(
+ height: height,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(borderRadius),
color: isSelected ? chipType.color : backgroundColor ?? chipType.backgroundColor,
diff --git a/lib/widgets/common_bottom_sheet.dart b/lib/widgets/common_bottom_sheet.dart
index 29df19b..c6db474 100644
--- a/lib/widgets/common_bottom_sheet.dart
+++ b/lib/widgets/common_bottom_sheet.dart
@@ -104,55 +104,137 @@ class ButtonSheetContent extends StatelessWidget {
}
}
-Future showCommonBottomSheetWithoutHeight(
- BuildContext context, {
- required Widget child,
- required VoidCallback callBackFunc,
- String title = "",
- bool isCloseButtonVisible = true,
- bool isFullScreen = true,
- bool isDismissible = true,
- Widget? titleWidget,
-}) async {
+void showCommonBottomSheetWithoutHeight(
+ BuildContext context, {
+ required Widget child,
+ required VoidCallback callBackFunc,
+ String title = "",
+ bool isCloseButtonVisible = true,
+ bool isFullScreen = true,
+ bool isDismissible = true,
+ Widget? titleWidget,
+ bool useSafeArea = false,
+ }) {
showModalBottomSheet(
- sheetAnimationStyle: AnimationStyle(
- duration: Duration(milliseconds: 500), // Custom animation duration
- reverseDuration: Duration(milliseconds: 300), // Custom reverse animation duration
- ),
- context: context,
- isScrollControlled: true,
- showDragHandle: false,
- isDismissible: isDismissible,
- backgroundColor: AppColors.bottomSheetBgColor,
- builder: (BuildContext context) {
- return SafeArea(
- top: false,
- left: false,
- right: false,
- child: isCloseButtonVisible
- ? Container(
- padding: EdgeInsets.only(left: 24, top: 24, right: 24, bottom: 12),
- decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.bottomSheetBgColor, borderRadius: 24.h),
- child: Column(
- mainAxisSize: MainAxisSize.min,
- spacing: 16.h,
+ sheetAnimationStyle: AnimationStyle(
+ duration: Duration(milliseconds: 500),
+ reverseDuration: Duration(milliseconds: 300),
+ ),
+ context: context,
+ isScrollControlled: true,
+ showDragHandle: false,
+ isDismissible: isDismissible,
+ backgroundColor: AppColors.bottomSheetBgColor,
+ useSafeArea: useSafeArea,
+ builder: (BuildContext context) {
+ return SafeArea(
+ top: false,
+ left: false,
+ right: false,
+ child: Padding(
+ padding: EdgeInsets.only(
+ bottom: MediaQuery.of(context).viewInsets.bottom,
+ ),
+ child: SingleChildScrollView(
+ physics: ClampingScrollPhysics(),
+ child: isCloseButtonVisible
+ ? Container(
+ padding: EdgeInsets.only(
+ left: 24,
+ top: 24,
+ right: 24,
+ bottom: 12,
+ ),
+ decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
+ color: AppColors.bottomSheetBgColor,
+ borderRadius: 24.h,
+ ),
+ child: Column(
+ mainAxisSize: MainAxisSize.min,
+ children: [
+ Row(
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ crossAxisAlignment: CrossAxisAlignment.center,
children: [
- Row(
- mainAxisAlignment: MainAxisAlignment.spaceBetween,
- crossAxisAlignment: CrossAxisAlignment.center,
- children: [
- titleWidget ?? Expanded(child: title.toText20(weight: FontWeight.w600)),
- Utils.buildSvgWithAssets(icon: AppAssets.close_bottom_sheet_icon, iconColor: Color(0xff2B353E)).onPress(() {
- Navigator.of(context).pop();
- }),
- ],
- ),
- child,
+ titleWidget ??
+ Expanded(
+ child: title.toText20(weight: FontWeight.w600),
+ ),
+ Utils.buildSvgWithAssets(
+ icon: AppAssets.close_bottom_sheet_icon,
+ iconColor: Color(0xff2B353E),
+ ).onPress(() {
+ Navigator.of(context).pop();
+ }),
],
- ))
- : child,
- );
- }).then((value) {
+ ),
+ SizedBox(height: 16.h),
+ child,
+ ],
+ ),
+ )
+ : child,
+ ),
+ ),
+ );
+ },
+ ).then((value) {
callBackFunc();
});
}
+
+// void showCommonBottomSheetWithoutHeight(
+// BuildContext context, {
+// required Widget child,
+// required VoidCallback callBackFunc,
+// String title = "",
+// bool isCloseButtonVisible = true,
+// bool isFullScreen = true,
+// bool isDismissible = true,
+// Widget? titleWidget,
+// bool useSafeArea = false,
+//
+// }) {
+// showModalBottomSheet(
+// sheetAnimationStyle: AnimationStyle(
+// duration: Duration(milliseconds: 500), // Custom animation duration
+// reverseDuration: Duration(milliseconds: 300), // Custom reverse animation duration
+// ),
+// context: context,
+// isScrollControlled: true,
+// showDragHandle: false,
+// isDismissible: isDismissible,
+// backgroundColor: AppColors.bottomSheetBgColor,
+// useSafeArea: useSafeArea,
+// builder: (BuildContext context) {
+// return SafeArea(
+// top: false,
+// left: false,
+// right: false,
+// child: isCloseButtonVisible
+// ? Container(
+// padding: EdgeInsets.only(left: 24, top: 24, right: 24, bottom: 12),
+// decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.bottomSheetBgColor, borderRadius: 24.h),
+// child: Column(
+// mainAxisSize: MainAxisSize.min,
+// spacing: 16.h,
+// children: [
+// Row(
+// mainAxisAlignment: MainAxisAlignment.spaceBetween,
+// crossAxisAlignment: CrossAxisAlignment.center,
+// children: [
+// titleWidget ?? Expanded(child: title.toText20(weight: FontWeight.w600)),
+// Utils.buildSvgWithAssets(icon: AppAssets.close_bottom_sheet_icon, iconColor: Color(0xff2B353E)).onPress(() {
+// Navigator.of(context).pop();
+// }),
+// ],
+// ),
+// child,
+// ],
+// ))
+// : child,
+// );
+// }).then((value) {
+// callBackFunc();
+// });
+// }
diff --git a/lib/widgets/family_files/family_file_add_widget.dart b/lib/widgets/family_files/family_file_add_widget.dart
new file mode 100644
index 0000000..8e57f91
--- /dev/null
+++ b/lib/widgets/family_files/family_file_add_widget.dart
@@ -0,0 +1,105 @@
+import 'package:easy_localization/easy_localization.dart';
+import 'package:flutter/cupertino.dart';
+import 'package:flutter/material.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/enums.dart';
+import 'package:hmg_patient_app_new/core/utils/size_utils.dart';
+import 'package:hmg_patient_app_new/core/utils/validation_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/features/authentication/authentication_view_model.dart';
+import 'package:hmg_patient_app_new/features/medical_file/medical_file_view_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/dropdown/country_dropdown_widget.dart';
+import 'package:hmg_patient_app_new/widgets/input_widget.dart';
+
+class FamilyFileAddWidget extends StatelessWidget {
+ final Function()? onVerificationPress;
+ final String message;
+
+ const FamilyFileAddWidget(this.onVerificationPress, this.message, {super.key});
+
+ @override
+ Widget build(BuildContext context) {
+ AuthenticationViewModel authVm = getIt.get();
+ MedicalFileViewModel? medicalVM = getIt.get();
+ // TODO: implement build
+ return Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ mainAxisAlignment: MainAxisAlignment.start,
+ mainAxisSize: MainAxisSize.min,
+ children: [
+ message.toText16(color: AppColors.textColor, weight: FontWeight.w500),
+ SizedBox(height: 20.h),
+ Container(
+ decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(24)),
+ padding: EdgeInsets.symmetric(horizontal: 16.h, vertical: 8.h),
+ child: Column(
+ children: [
+ CustomCountryDropdown(
+ countryList: CountryEnum.values,
+ onCountryChange: authVm.onCountryChange,
+ ).paddingOnly(top: 8.h, bottom: 16.h),
+ Divider(height: 1.h, color: AppColors.spacerLineColor),
+ TextInputWidget(
+ labelText: LocaleKeys.nationalIdNumber.tr(),
+ hintText: "xxxxxxxxx",
+ controller: authVm.nationalIdController,
+ isEnable: true,
+ prefix: null,
+ isAllowRadius: true,
+ isBorderAllowed: false,
+ isAllowLeadingIcon: true,
+ autoFocus: true,
+ keyboardType: TextInputType.number,
+ padding: EdgeInsets.symmetric(vertical: 8.h),
+ leadingIcon: AppAssets.student_card,
+ ).paddingOnly(top: 8.h, bottom: 8.h),
+ Divider(height: 1.h, color: AppColors.spacerLineColor),
+ TextInputWidget(
+ labelText: LocaleKeys.phoneNumber.tr(),
+ hintText: "",
+ controller: authVm.phoneNumberController,
+ isEnable: true,
+ prefix: authVm.selectedCountrySignup.countryCode,
+ isAllowRadius: true,
+ isBorderAllowed: false,
+ isAllowLeadingIcon: true,
+ autoFocus: true,
+ keyboardType: TextInputType.number,
+ padding: EdgeInsets.symmetric(vertical: 8.h),
+ leadingIcon: AppAssets.smart_phone,
+ ).paddingOnly(top: 8.h, bottom: 4.h),
+ ],
+ ),
+ ),
+ SizedBox(height: 20.h),
+ CustomButton(
+ text: "Verify the member".needTranslation,
+ onPressed: () {
+ FocusScope.of(context).unfocus();
+ if (ValidationUtils.isValidatedIdAndPhoneWithCountryValidation(
+ nationalId: authVm.nationalIdController.text,
+ selectedCountry: authVm.selectedCountrySignup,
+ phoneNumber: authVm.phoneNumberController.text,
+ onOkPress: () {
+ Navigator.of(context).pop();
+ },
+ )) {
+ // authVm.addFamilyMember(otpTypeEnum: OTPTypeEnum.sms, isExcludedUser: true);
+ if (onVerificationPress != null) {
+ onVerificationPress!();
+ }
+ }
+ },
+ icon: AppAssets.add_icon,
+ height: 56.h,
+ fontWeight: FontWeight.w600),
+ SizedBox(height: 20.h),
+ ],
+ );
+ }
+}