diff --git a/assets/images/png/baby_girl_img.png b/assets/images/png/baby_girl_img.png
new file mode 100644
index 0000000..55cee71
Binary files /dev/null and b/assets/images/png/baby_girl_img.png differ
diff --git a/assets/images/png/baby_img.png b/assets/images/png/baby_img.png
new file mode 100644
index 0000000..a4f3f86
Binary files /dev/null and b/assets/images/png/baby_img.png differ
diff --git a/assets/images/png/female_img.png b/assets/images/png/female_img.png
index 3307034..7d3354a 100644
Binary files a/assets/images/png/female_img.png and b/assets/images/png/female_img.png differ
diff --git a/assets/images/png/male_img.png b/assets/images/png/male_img.png
index 21932cd..f849800 100644
Binary files a/assets/images/png/male_img.png and b/assets/images/png/male_img.png differ
diff --git a/assets/images/svg/heart.svg b/assets/images/svg/heart.svg
new file mode 100644
index 0000000..6b0939a
--- /dev/null
+++ b/assets/images/svg/heart.svg
@@ -0,0 +1,3 @@
+
diff --git a/assets/langs/ar-SA.json b/assets/langs/ar-SA.json
index 19111f7..e824ca2 100644
--- a/assets/langs/ar-SA.json
+++ b/assets/langs/ar-SA.json
@@ -126,7 +126,7 @@
"gregorianDate": "التاريخ الميلادي",
"verifyLoginWith": "يرجى اختيار واحدة من الخيارات التالية للتحقق",
"registerUser": "تسجيل",
- "verifyWithFingerprint": "بصمة الإصبع",
+ "verifyWithFingerprint":"البيومترية",
"verifyWithFaceid": "معرف الوجه",
"verifyWithSms": "رسالة قصيرة",
"verifyWithWhatsapp": "واتساب",
diff --git a/assets/langs/en-US.json b/assets/langs/en-US.json
index 27609c8..86a4c25 100644
--- a/assets/langs/en-US.json
+++ b/assets/langs/en-US.json
@@ -126,7 +126,7 @@
"gregorianDate": "Gregorian Date",
"verifyLoginWith": "Please choose one of the following options to verify",
"registerUser": "Register",
- "verifyWithFingerprint": "Fingerprint",
+ "verifyWithFingerprint": "Biometric",
"verifyWithFaceid": "Face ID",
"verifyWithSms": "SMS",
"verifyWithWhatsapp": "Whatsapp",
@@ -561,12 +561,12 @@
"selectTamaraPlan": "Select Tamara Payment Plan",
"changeMethod": "Change Method",
"reviewOrder": "Review Order",
- "active": "ACTIVE",
- "inactive": "INACTIVE",
- "balance": "BALANCE",
+ "active": "Active",
+ "inactive": "InActive",
+ "balance": "Balance",
"gained": "GAINED",
"consumed": "Consumed",
- "transferred": "TRANSFERRED",
+ "transferred": "Transferred",
"riyal": "RIYAL",
"membersince": "MEMBER SINCE",
"identification": "رقم الهوية",
diff --git a/lib/core/api_consts.dart b/lib/core/api_consts.dart
index f802818..5886dfa 100644
--- a/lib/core/api_consts.dart
+++ b/lib/core/api_consts.dart
@@ -720,10 +720,14 @@ const SAVE_SETTING = 'Services/Patients.svc/REST/UpdatePateintInfo';
const DEACTIVATE_ACCOUNT = 'Services/Patients.svc/REST/PatientAppleActivation_InsertUpdate';
+//family Files
+
+const FAMILY_FILES= 'Services/Authentication.svc/REST/GetAllSharedRecordsByStatus';
+
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
@@ -803,6 +807,8 @@ class ApiConsts {
static final String getPrivileges = 'Services/Patients.svc/REST/Service_Privilege';
static final String registerUser = 'Services/Authentication.svc/REST/PatientRegistration';
+ static final String addFamilyFile = 'Services/Patients.svc/REST/ShareFamilyFileService';
+
// static values for Api
static final double appVersionID = 18.7;
static final int appChannelId = 3;
diff --git a/lib/core/app_assets.dart b/lib/core/app_assets.dart
index 57e0ebc..3f48a3f 100644
--- a/lib/core/app_assets.dart
+++ b/lib/core/app_assets.dart
@@ -143,12 +143,15 @@ class AppAssets {
static const String closeBottomNav = '$svgBasePath/close_bottom_nav.svg';
static const String feedback = '$svgBasePath/feedback.svg';
static const String news = '$svgBasePath/news.svg';
+ static const String heart = '$svgBasePath/heart.svg';
// PNGS //
static const String hmg_logo = '$pngBasePath/hmg_logo.png';
static const String livecare_service = '$pngBasePath/livecare_service.png';
static const String male_img = '$pngBasePath/male_img.png';
static const String femaleImg = '$pngBasePath/female_img.png';
+ static const String babyGirlImg = '$pngBasePath/baby_girl_img.png';
+ static const String babyBoyImg = '$pngBasePath/baby_img.png';
static const String apple_pay = '$pngBasePath/Apple_Pay.png';
static const String mada = '$pngBasePath/Mada.png';
static const String Mastercard = '$pngBasePath/Mastercard.png';
diff --git a/lib/core/enums.dart b/lib/core/enums.dart
index d4eafff..bb6c6fe 100644
--- a/lib/core/enums.dart
+++ b/lib/core/enums.dart
@@ -8,22 +8,9 @@
import 'package:hmg_patient_app_new/core/app_state.dart';
import 'package:hmg_patient_app_new/core/dependencies.dart';
-enum AuthMethodTypesEnum {
- sms,
- whatsApp,
- fingerPrint,
- faceID,
- moreOptions,
-}
+enum AuthMethodTypesEnum { sms, whatsApp, fingerPrint, faceID, moreOptions }
-enum ViewStateEnum {
- hide,
- idle,
- busy,
- error,
- busyLocal,
- errorLocal,
-}
+enum ViewStateEnum { hide, idle, busy, error, busyLocal, errorLocal }
enum CountryEnum { saudiArabia, unitedArabEmirates }
@@ -35,7 +22,7 @@ enum GenderTypeEnum { male, female }
enum MaritalStatusTypeEnum { single, married, divorced, widowed }
-enum ChipTypeEnum { success, error, alert, info, warning }
+enum ChipTypeEnum { success, error, alert, info, warning, lightBg, primaryRed }
enum OTPTypeEnum { sms, whatsapp, faceIDFingerprint }
diff --git a/lib/core/location_util.dart b/lib/core/location_util.dart
index ecfab62..b2b4fca 100644
--- a/lib/core/location_util.dart
+++ b/lib/core/location_util.dart
@@ -8,16 +8,9 @@ import 'package:hmg_patient_app_new/core/app_state.dart';
import 'package:hmg_patient_app_new/core/cache_consts.dart';
import 'package:hmg_patient_app_new/core/utils/utils.dart';
import 'package:hmg_patient_app_new/services/navigation_service.dart';
-import 'package:huawei_location/huawei_location.dart' as HmsLocation
- show
- FusedLocationProviderClient,
- Location,
- LocationSettingsRequest,
- LocationRequest;
-import 'package:location/location.dart'
- show Location, PermissionStatus, LocationData;
-import 'package:permission_handler/permission_handler.dart'
- show Permission, PermissionListActions, PermissionStatusGetters;
+import 'package:huawei_location/huawei_location.dart' as HmsLocation show FusedLocationProviderClient, Location, LocationSettingsRequest, LocationRequest;
+import 'package:location/location.dart' show Location, PermissionStatus, LocationData;
+import 'package:permission_handler/permission_handler.dart' show Permission, PermissionListActions, PermissionStatusGetters;
class LocationUtils {
NavigationService navigationService;
@@ -39,8 +32,7 @@ class LocationUtils {
isGMSDevice = GmsCheck().checkGmsAvailability();
}
- void getLocation(
- {Function(LatLng)? onSuccess, VoidCallback? onFailure}) async {
+ void getLocation({Function(LatLng)? onSuccess, VoidCallback? onFailure}) async {
if (Platform.isIOS) {
getCurrentLocation(onFailure: onFailure, onSuccess: onSuccess);
return;
@@ -54,8 +46,7 @@ class LocationUtils {
getHMSLocation(onFailure: onFailure, onSuccess: onSuccess);
}
- void getCurrentLocation(
- {Function(LatLng)? onSuccess, VoidCallback? onFailure}) async {
+ void getCurrentLocation({Function(LatLng)? onSuccess, VoidCallback? onFailure}) async {
var location = Location();
bool isLocationEnabled = await location.serviceEnabled();
@@ -72,8 +63,7 @@ class LocationUtils {
LocationPermission permissionGranted = await Geolocator.checkPermission();
if (permissionGranted == LocationPermission.denied) {
permissionGranted = await Geolocator.requestPermission();
- if (permissionGranted != LocationPermission.whileInUse &&
- permissionGranted != LocationPermission.always) {
+ if (permissionGranted != LocationPermission.whileInUse && permissionGranted != LocationPermission.always) {
appState.resetLocation();
onFailure?.call();
return;
@@ -82,13 +72,11 @@ class LocationUtils {
Position? currentLocation = await Geolocator.getLastKnownPosition();
- if(currentLocation?.latitude == null || currentLocation?.longitude == null){
- currentLocation = await Geolocator.getCurrentPosition(
- desiredAccuracy: LocationAccuracy.low);
+ if (currentLocation?.latitude == null || currentLocation?.longitude == null) {
+ currentLocation = await Geolocator.getCurrentPosition(desiredAccuracy: LocationAccuracy.low);
}
- LatLng locationData = LatLng(
- currentLocation?.latitude ?? 0.0, currentLocation?.longitude ?? 0.0);
+ LatLng locationData = LatLng(currentLocation?.latitude ?? 0.0, currentLocation?.longitude ?? 0.0);
saveLatLngToAppState(locationData);
onSuccess?.call(locationData);
}
@@ -197,22 +185,17 @@ class LocationUtils {
appState.userLong = locationData.longitude;
}
- void getHMSLocation(
- {VoidCallback? onFailure, Function(LatLng p1)? onSuccess}) async {
+ void getHMSLocation({VoidCallback? onFailure, Function(LatLng p1)? onSuccess}) async {
try {
var location = Location();
- HmsLocation.FusedLocationProviderClient locationService =
- HmsLocation.FusedLocationProviderClient()..initFusedLocationService();
+ HmsLocation.FusedLocationProviderClient locationService = HmsLocation.FusedLocationProviderClient()..initFusedLocationService();
bool isLocationEnabled = await Geolocator.isLocationServiceEnabled();
//if the location service is not enabled, ask the user to enable it
if (!isLocationEnabled) {
- HmsLocation.LocationRequest locationRequest =
- HmsLocation.LocationRequest()
- ..priority = HmsLocation.LocationRequest.PRIORITY_HIGH_ACCURACY;
+ HmsLocation.LocationRequest locationRequest = HmsLocation.LocationRequest()..priority = HmsLocation.LocationRequest.PRIORITY_HIGH_ACCURACY;
- HmsLocation.LocationSettingsRequest request =
- HmsLocation.LocationSettingsRequest(
+ HmsLocation.LocationSettingsRequest request = HmsLocation.LocationSettingsRequest(
alwaysShow: true,
needBle: false,
requests: [locationRequest],
@@ -223,8 +206,7 @@ class LocationUtils {
LocationPermission permissionGranted = await Geolocator.checkPermission();
if (permissionGranted == LocationPermission.denied) {
permissionGranted = await Geolocator.requestPermission();
- if (permissionGranted != LocationPermission.whileInUse &&
- permissionGranted != LocationPermission.always) {
+ if (permissionGranted != LocationPermission.whileInUse && permissionGranted != LocationPermission.always) {
appState.resetLocation();
onFailure?.call();
return;
@@ -246,8 +228,7 @@ class LocationUtils {
onFailure?.call();
return;
}
- var locationData =
- LatLng(data.latitude ?? 0.0, data.longitude ?? 0.0);
+ var locationData = LatLng(data.latitude ?? 0.0, data.longitude ?? 0.0);
saveLatLngToAppState(locationData);
onSuccess?.call(locationData);
});
diff --git a/lib/core/utils/request_utils.dart b/lib/core/utils/request_utils.dart
index 00bfc94..8b993f1 100644
--- a/lib/core/utils/request_utils.dart
+++ b/lib/core/utils/request_utils.dart
@@ -246,4 +246,20 @@ class RequestUtils {
if (!isDubai) "HealthId": appState.getNHICUserData.healthId,
};
}
+
+ static dynamic getAddFamilyRequest({required String nationalIDorFile, required String mobileNo, required String countryCode, required int loginType}) {
+ var request = {};
+ if (loginType == 1) {
+ request["sharedPatientID"] = 0;
+ request["sharedPatientIdentificationID"] = nationalIDorFile;
+ } else if (loginType == 2) {
+ request["sharedPatientID"] = int.parse(nationalIDorFile);
+ request["sharedPatientIdentificationID"] = '';
+ }
+ request["searchType"] = loginType;
+ request["sharedPatientMobileNumber"] = mobileNo;
+ request["zipCode"] = countryCode;
+ request["isRegister"] = false;
+ request["patientStatus"] = 2;
+ }
}
diff --git a/lib/core/utils/utils.dart b/lib/core/utils/utils.dart
index e0eeb23..698075d 100644
--- a/lib/core/utils/utils.dart
+++ b/lib/core/utils/utils.dart
@@ -606,6 +606,27 @@ class Utils {
);
}
+ static Widget buildImgWithAssets({
+ required String icon,
+ Color? iconColor,
+ bool isDisabled = false,
+ double width = 24,
+ double height = 24,
+ BoxFit fit = BoxFit.cover,
+ }) {
+ return Image.asset(icon, width: width, height: height, fit: fit);
+ }
+
+ /// Widget to build an SVG from network
+ static Widget buildImgWithNetwork({required String url, required Color iconColor, bool isDisabled = false, double width = 24, double height = 24, BoxFit fit = BoxFit.cover}) {
+ return Image.network(
+ url,
+ width: width,
+ height: height,
+ fit: fit,
+ );
+ }
+
static Widget getPaymentMethods() {
return Row(
mainAxisSize: MainAxisSize.max,
diff --git a/lib/core/utils/validation_utils.dart b/lib/core/utils/validation_utils.dart
index e335c6b..4f02ad9 100644
--- a/lib/core/utils/validation_utils.dart
+++ b/lib/core/utils/validation_utils.dart
@@ -140,4 +140,34 @@ class ValidationUtils {
return true;
}
+
+ static bool isValidatedIdAndPhoneWithCountryValidation({String? nationalId, String? phoneNumber, required Function() onOkPress, CountryEnum? selectedCountry}) {
+ bool isCorrectID = true;
+ if (nationalId == null || nationalId.isEmpty) {
+ _dialogService.showExceptionBottomSheet(message: LocaleKeys.pleaseEnterAnationalID.tr(), onOkPressed: onOkPress);
+ isCorrectID = false;
+ }
+
+ if (nationalId != null && nationalId.isNotEmpty && selectedCountry != null) {
+ if (selectedCountry == CountryEnum.saudiArabia) {
+ if (!validateIqama(nationalId)) {
+ _dialogService.showExceptionBottomSheet(message: LocaleKeys.pleaseEnterAValidIqamaID.tr(), onOkPressed: onOkPress);
+ return false;
+ }
+ }
+
+ if (selectedCountry == CountryEnum.unitedArabEmirates) {
+ if (!validateUaeNationalId(nationalId)) {
+ _dialogService.showExceptionBottomSheet(message: LocaleKeys.pleaseEnterAValidNationalID.tr(), onOkPressed: onOkPress);
+ return false;
+ }
+ }
+
+ if (phoneNumber == null || phoneNumber.isEmpty) {
+ _dialogService.showExceptionBottomSheet(message: LocaleKeys.enterValidPhoneNumber.tr(), onOkPressed: onOkPress);
+ return false;
+ }
+ }
+ return isCorrectID;
+ }
}
diff --git a/lib/extensions/widget_extensions.dart b/lib/extensions/widget_extensions.dart
index 26a1442..5f2cc98 100644
--- a/lib/extensions/widget_extensions.dart
+++ b/lib/extensions/widget_extensions.dart
@@ -233,6 +233,10 @@ extension ChipTypeEnumExtension on ChipTypeEnum {
return AppColors.infoColor; // Replace with your actual color
case ChipTypeEnum.warning:
return AppColors.warningColor; // Replace with your actual color
+ case ChipTypeEnum.lightBg:
+ return AppColors.chipPrimaryRedBorderColor; // Replace with your actual color
+ case ChipTypeEnum.primaryRed:
+ return AppColors.chipSecondaryLightRedColor; // Replace with your actual color
}
}
@@ -248,6 +252,10 @@ extension ChipTypeEnumExtension on ChipTypeEnum {
return AppColors.infoLightColor; // Replace with your actual color
case ChipTypeEnum.warning:
return AppColors.warningLightColor; // Replace with your actual color
+ case ChipTypeEnum.lightBg:
+ return AppColors.chipSecondaryLightRedColor; // Replace with your actual color
+ case ChipTypeEnum.primaryRed:
+ return AppColors.chipPrimaryRedBorderColor;
}
}
}
diff --git a/lib/features/lab/lab_view_model.dart b/lib/features/lab/lab_view_model.dart
index 2e481f4..29b90f8 100644
--- a/lib/features/lab/lab_view_model.dart
+++ b/lib/features/lab/lab_view_model.dart
@@ -17,6 +17,8 @@ class LabViewModel extends ChangeNotifier {
List get labSuggestions => _labSuggestionsList;
+ Set uniqueTests = {};
+
LabViewModel({required this.labRepo, required this.errorHandlerService});
initLabProvider() {
@@ -32,8 +34,8 @@ class LabViewModel extends ChangeNotifier {
final result = await labRepo.getPatientLabOrders();
result.fold(
- (failure) async => await errorHandlerService.handleError(failure: failure),
- (apiResponse) {
+ (failure) async => await errorHandlerService.handleError(failure: failure),
+ (apiResponse) {
if (apiResponse.messageStatus == 2) {
// dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {});
} else if (apiResponse.messageStatus == 1) {
@@ -43,6 +45,7 @@ class LabViewModel extends ChangeNotifier {
isLabOrdersLoading = false;
isLabResultsLoading = false;
filterSuggestions();
+ getUniqueTestDescription();
notifyListeners();
if (onSuccess != null) {
onSuccess(apiResponse);
@@ -75,4 +78,15 @@ class LabViewModel extends ChangeNotifier {
}
notifyListeners();
}
+
+ getUniqueTestDescription() {
+
+ uniqueTests = {
+ for (var item in patientLabOrders)
+ if (item.testDetails != null)
+ ...?item.testDetails?.map((test) =>
+ TestDetails(description: test.description.toString(), testCode: test.testCode.toString(), testID: test.testID, createdOn: item.createdOn))
+ };
+ uniqueTests.forEach(print);
+ }
}
diff --git a/lib/features/lab/models/resp_models/patient_lab_orders_response_model.dart b/lib/features/lab/models/resp_models/patient_lab_orders_response_model.dart
index 11bf573..265a19e 100644
--- a/lib/features/lab/models/resp_models/patient_lab_orders_response_model.dart
+++ b/lib/features/lab/models/resp_models/patient_lab_orders_response_model.dart
@@ -226,13 +226,14 @@ class TestDetails {
String? description;
String? testCode;
String? testID;
-
- TestDetails({this.description, this.testCode, this.testID});
+ String? createdOn;
+ TestDetails({this.description, this.testCode, this.testID, this.createdOn});
TestDetails.fromJson(Map json) {
description = json['Description'];
testCode = json['TestCode'];
testID = json['TestID'];
+ createdOn = json['CreatedOn'];
}
Map toJson() {
@@ -240,6 +241,7 @@ class TestDetails {
data['Description'] = this.description;
data['TestCode'] = this.testCode;
data['TestID'] = this.testID;
+ data['CreatedOn'] = this.createdOn;
return data;
}
}
diff --git a/lib/features/medical_file/medical_file_repo.dart b/lib/features/medical_file/medical_file_repo.dart
index bbb4fcd..6b83f33 100644
--- a/lib/features/medical_file/medical_file_repo.dart
+++ b/lib/features/medical_file/medical_file_repo.dart
@@ -11,6 +11,7 @@ import 'package:hmg_patient_app_new/features/medical_file/models/patient_vaccine
import 'package:hmg_patient_app_new/services/logger_service.dart';
import '../authentication/models/resp_models/authenticated_user_resp_model.dart';
+import 'models/family_file_response_model.dart';
abstract class MedicalFileRepo {
Future>>> getPatientVaccinesList();
@@ -22,6 +23,10 @@ abstract class MedicalFileRepo {
Future>>> getPatientMedicalReportsList();
Future>> getPatientMedicalReportPDF(PatientMedicalReportResponseModel patientMedicalReportResponseModel, AuthenticatedUser authenticatedUser);
+
+ Future>>> getPatientFamilyFiles();
+
+ Future>>> addFamilyFile({required dynamic request});
}
class MedicalFileRepoImp implements MedicalFileRepo {
@@ -267,4 +272,80 @@ class MedicalFileRepoImp implements MedicalFileRepo {
return Left(UnknownFailure(e.toString()));
}
}
+
+ @override
+ Future>>> getPatientFamilyFiles() async {
+ try {
+ GenericApiModel>? apiResponse;
+ Failure? failure;
+ await apiClient.post(
+ FAMILY_FILES,
+ body: {"Status": 3},
+ onFailure: (error, statusCode, {messageStatus, failureType}) {
+ failure = failureType;
+ },
+ onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
+ try {
+ final list = response['GetAllSharedRecordsByStatusList'];
+ // if (list == null || list.isEmpty) {
+ // throw Exception("lab list is empty");
+ // }
+
+ 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,
+ body: request,
+ onFailure: (error, statusCode, {messageStatus, failureType}) {
+ failure = failureType;
+ },
+ 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,
+ // );
+ } 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()));
+ }
+ }
}
diff --git a/lib/features/medical_file/medical_file_view_model.dart b/lib/features/medical_file/medical_file_view_model.dart
index 73167bb..2e528de 100644
--- a/lib/features/medical_file/medical_file_view_model.dart
+++ b/lib/features/medical_file/medical_file_view_model.dart
@@ -1,9 +1,14 @@
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/utils/request_utils.dart';
import 'package:hmg_patient_app_new/features/authentication/models/resp_models/authenticated_user_resp_model.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';
import 'package:hmg_patient_app_new/features/medical_file/models/patient_sickleave_response_model.dart';
import 'package:hmg_patient_app_new/features/medical_file/models/patient_vaccine_response_model.dart';
+import 'package:hmg_patient_app_new/services/dialog_service.dart';
import 'package:hmg_patient_app_new/services/error_handler_service.dart';
class MedicalFileViewModel extends ChangeNotifier {
@@ -25,10 +30,14 @@ class MedicalFileViewModel extends ChangeNotifier {
List patientMedicalReportReadyList = [];
List patientMedicalReportCancelledList = [];
+ List patientFamilyFiles = [];
+
String patientSickLeavePDFBase64 = "";
String patientMedicalReportPDFBase64 = "";
int selectedMedicalReportsTabIndex = 0;
+ static final DialogService _dialogService = getIt.get();
+ AppState _appState = getIt();
MedicalFileViewModel({required this.medicalFileRepo, required this.errorHandlerService});
@@ -217,4 +226,76 @@ class MedicalFileViewModel extends ChangeNotifier {
},
);
}
+
+ Future getFamilyFiles({Function(dynamic)? onSuccess, Function(String)? onError}) async {
+ final result = await medicalFileRepo.getPatientFamilyFiles();
+
+ result.fold(
+ (failure) async => await errorHandlerService.handleError(
+ failure: failure,
+ onOkPressed: () {
+ onError!(failure.message);
+ },
+ ),
+ (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);
+ }
+ }
+ },
+ );
+ }
+
+ Future switchFamilyFiles({Function(dynamic)? onSuccess, Function(String)? onError}) async {
+ final result = await medicalFileRepo.getPatientFamilyFiles();
+
+ result.fold(
+ (failure) async => await errorHandlerService.handleError(
+ failure: failure,
+ onOkPressed: () {
+ onError!(failure.message);
+ },
+ ),
+ (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);
+ }
+ }
+ },
+ );
+ }
+
+ Future addFamilyFile() async {
+ final resultEither = await medicalFileRepo.addFamilyFile(request: {});
+ resultEither.fold((failure) async => await errorHandlerService.handleError(failure: failure), (apiResponse) async {});
+ }
+
}
diff --git a/lib/features/medical_file/models/family_file_response_model.dart b/lib/features/medical_file/models/family_file_response_model.dart
new file mode 100644
index 0000000..82fe3d8
--- /dev/null
+++ b/lib/features/medical_file/models/family_file_response_model.dart
@@ -0,0 +1,105 @@
+import 'dart:convert';
+
+class FamilyFileResponseModelLists {
+ int? id;
+ int? patientId;
+ int? responseId;
+ dynamic relationshipId;
+ dynamic relationship;
+ dynamic relationshipN;
+ int? regionId;
+ int? familyRegionId;
+ int? status;
+ dynamic isActive;
+ String? editedOn;
+ String? createdOn;
+ int? age;
+ String? emaiLAddress;
+ int? gender;
+ String? genderDescription;
+ String? genderImage;
+ String? mobileNumber;
+ int? patientDataVerified;
+ String? patientIdenficationNumber;
+ String? patientName;
+ String? 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,
+ });
+
+ 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"],
+ );
+
+ 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,
+ };
+}
diff --git a/lib/presentation/lab/lab_order_by_test.dart b/lib/presentation/lab/lab_order_by_test.dart
new file mode 100644
index 0000000..e5c6929
--- /dev/null
+++ b/lib/presentation/lab/lab_order_by_test.dart
@@ -0,0 +1,84 @@
+import 'package:easy_localization/easy_localization.dart';
+import 'package:flutter/material.dart';
+import 'package:hmg_patient_app_new/core/app_assets.dart';
+import 'package:hmg_patient_app_new/core/app_export.dart';
+import 'package:hmg_patient_app_new/core/enums.dart';
+import 'package:hmg_patient_app_new/core/utils/date_util.dart';
+import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
+import 'package:hmg_patient_app_new/extensions/widget_extensions.dart';
+import 'package:hmg_patient_app_new/features/lab/models/resp_models/patient_lab_orders_response_model.dart';
+import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
+import 'package:hmg_patient_app_new/theme/colors.dart';
+import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart';
+import 'package:hmg_patient_app_new/widgets/chip/app_custom_chip_widget.dart';
+import 'package:hmg_patient_app_new/widgets/chip/custom_chip_widget.dart';
+
+class LabOrderByTest extends StatelessWidget {
+ final VoidCallback onTap;
+ final int index;
+ final TestDetails? tests;
+ final bool isLoading;
+ final bool isExpanded;
+
+ const LabOrderByTest({super.key, required this.onTap, this.tests, required this.index, this.isLoading = false, this.isExpanded = false});
+
+ @override
+ build(BuildContext context) {
+ return AnimatedContainer(
+ duration: Duration(milliseconds: 300),
+ curve: Curves.easeInOut,
+ margin: EdgeInsets.symmetric(vertical: 8.h),
+ decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 20.h, hasShadow: true),
+ child: InkWell(
+ onTap: () {
+ if (!isLoading) {
+ onTap();
+ }
+ },
+ child: Container(
+ key: ValueKey(index),
+ padding: EdgeInsets.symmetric(horizontal: 16.h, vertical: 8.h),
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ // ...labOrder!.testDetails!.map((detail) {
+ Padding(
+ padding: EdgeInsets.only(bottom: 8.h),
+ child: '${tests!.description}'.toText14(weight: FontWeight.w500),
+ ),
+
+ SizedBox(height: 12.h),
+
+ Row(
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ children: [
+ AppCustomChipWidget(
+ richText: '${"Last Tested:".needTranslation} ${ DateUtil.formatDateToDate(DateUtil.convertStringToDate(tests!.createdOn), false)}'.toText12(isBold: true),
+ // chipType: ChipTypeEnum.lightBg,
+ backgroundColor: AppColors.greyLightColor,
+ textColor: AppColors.textColor,
+ // borderRadius: 5,
+
+ ),
+ CustomButton(
+ icon: AppAssets.view_report_icon,
+ iconColor: AppColors.primaryRedColor,
+ iconSize: 16.h,
+ text: LocaleKeys.viewReport.tr(context: context),
+ onPressed: () {},
+ backgroundColor: AppColors.secondaryLightRedColor,
+ borderColor: AppColors.secondaryLightRedColor,
+ textColor: AppColors.primaryRedColor,
+ fontSize: 14,
+ fontWeight: FontWeight.bold,
+ borderRadius: 12,
+ padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
+ height: 40.h,
+ ),
+ ],
+ ),
+ ],
+ ),
+ )));
+ }
+}
diff --git a/lib/presentation/lab/lab_orders_page.dart b/lib/presentation/lab/lab_orders_page.dart
index 0e14565..3d7edb9 100644
--- a/lib/presentation/lab/lab_orders_page.dart
+++ b/lib/presentation/lab/lab_orders_page.dart
@@ -11,6 +11,7 @@ import 'package:hmg_patient_app_new/extensions/widget_extensions.dart';
import 'package:hmg_patient_app_new/features/lab/models/resp_models/patient_lab_orders_response_model.dart';
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
import 'package:hmg_patient_app_new/features/lab/lab_view_model.dart';
+import 'package:hmg_patient_app_new/presentation/lab/lab_order_by_test.dart';
import 'package:hmg_patient_app_new/presentation/lab/lab_result_item_view.dart';
import 'package:hmg_patient_app_new/presentation/lab/search_lab_report.dart';
import 'package:hmg_patient_app_new/theme/colors.dart';
@@ -32,7 +33,7 @@ class _LabOrdersPageState extends State {
List?> labSuggestions = [];
int? expandedIndex;
String? selectedFilterText = '';
-
+ int activeIndex = 0;
@override
void initState() {
scheduleMicrotask(() {
@@ -78,7 +79,10 @@ class _LabOrdersPageState extends State {
// CustomTabBarModel(null, "Completed".needTranslation),
],
onTabChange: (index) {
- // myAppointmentsViewModel.onTabChange(index);
+ activeIndex = index;
+ setState(() {
+
+ });
},
),
SizedBox(height: 16.h),
@@ -89,39 +93,73 @@ class _LabOrdersPageState extends State {
isSelected: true,
)
: SizedBox(),
- ListView.builder(
- shrinkWrap: true,
- physics: NeverScrollableScrollPhysics(),
- padding: EdgeInsets.zero,
- itemCount: model.isLabOrdersLoading ? 5 : model.patientLabOrders.length,
- itemBuilder: (context, index) {
- final isExpanded = expandedIndex == index;
- return model.isLabOrdersLoading
- ? LabResultItemView(
+ activeIndex == 0
+ ? ListView.builder(
+ shrinkWrap: true,
+ physics: NeverScrollableScrollPhysics(),
+ padding: EdgeInsets.zero,
+ itemCount: model.isLabOrdersLoading ? 5 : model.patientLabOrders.length,
+ itemBuilder: (context, index) {
+ final isExpanded = expandedIndex == index;
+ return model.isLabOrdersLoading
+ ? LabResultItemView(
+ onTap: () {},
+ labOrder: null,
+ index: index,
+ isLoading: true,
+ )
+ : AnimationConfiguration.staggeredList(
+ position: index,
+ duration: const Duration(milliseconds: 500),
+ child: SlideAnimation(
+ verticalOffset: 100.0,
+ child: FadeInAnimation(
+ child: LabResultItemView(
+ onTap: () {
+ setState(() {
+ expandedIndex = isExpanded ? null : index;
+ });
+ },
+ labOrder: model.patientLabOrders[index],
+ index: index,
+ isExpanded: isExpanded)),
+ ),
+ );
+ },
+ )
+ : ListView.builder(
+ shrinkWrap: true,
+ physics: NeverScrollableScrollPhysics(),
+ padding: EdgeInsets.zero,
+ itemCount: model.isLabOrdersLoading ? 5 :model.uniqueTests.toList().length,
+ itemBuilder: (context, index) {
+ final isExpanded = expandedIndex == index;
+ return model.isLabOrdersLoading
+ ? LabResultItemView(
onTap: () {},
labOrder: null,
index: index,
isLoading: true,
- )
- : AnimationConfiguration.staggeredList(
- position: index,
- duration: const Duration(milliseconds: 500),
- child: SlideAnimation(
- verticalOffset: 100.0,
- child: FadeInAnimation(
- child: LabResultItemView(
- onTap: () {
- setState(() {
- expandedIndex = isExpanded ? null : index;
- });
- },
- labOrder: model.patientLabOrders[index],
- index: index,
- isExpanded: isExpanded)),
- ),
- );
- },
- ),
+ ) : AnimationConfiguration.staggeredList(
+ position: index,
+ duration: const Duration(milliseconds: 500),
+ child: SlideAnimation(
+ verticalOffset: 100.0,
+ child: FadeInAnimation(
+ child: LabOrderByTest(
+ onTap: () {
+ setState(() {
+ expandedIndex = isExpanded ? null : index;
+ });
+ },
+ tests: model.uniqueTests.toList()[index],
+ index: index,
+ isExpanded: isExpanded)),
+ ),
+ );
+
+ },
+ )
],
);
},
diff --git a/lib/presentation/medical_file/medical_file_page.dart b/lib/presentation/medical_file/medical_file_page.dart
index 43f0537..18b6085 100644
--- a/lib/presentation/medical_file/medical_file_page.dart
+++ b/lib/presentation/medical_file/medical_file_page.dart
@@ -4,9 +4,11 @@ import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:flutter_staggered_animations/flutter_staggered_animations.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/utils/date_util.dart';
+import 'package:hmg_patient_app_new/core/utils/request_utils.dart';
import 'package:hmg_patient_app_new/core/utils/size_utils.dart';
import 'package:hmg_patient_app_new/core/utils/utils.dart';
import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
@@ -15,6 +17,7 @@ import 'package:hmg_patient_app_new/features/book_appointments/book_appointments
import 'package:hmg_patient_app_new/features/book_appointments/models/resp_models/doctors_list_response_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/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';
@@ -33,7 +36,10 @@ import 'package:hmg_patient_app_new/presentation/medical_file/vaccine_list_page.
import 'package:hmg_patient_app_new/presentation/medical_file/widgets/lab_rad_card.dart';
import 'package:hmg_patient_app_new/presentation/medical_file/widgets/medical_file_card.dart';
import 'package:hmg_patient_app_new/presentation/medical_file/widgets/patient_sick_leave_card.dart';
+import 'package:hmg_patient_app_new/presentation/my_family/my_Family.dart';
+import 'package:hmg_patient_app_new/presentation/my_family/widget/my_family_sheet.dart';
import 'package:hmg_patient_app_new/presentation/prescriptions/prescriptions_list_page.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/app_custom_chip_widget.dart';
@@ -72,6 +78,7 @@ class _MedicalFilePageState extends State {
insuranceViewModel.initInsuranceProvider();
medicalFileViewModel.setIsPatientSickLeaveListLoading(true);
medicalFileViewModel.getPatientSickLeaveList();
+ medicalFileViewModel.getFamilyFiles();
medicalFileViewModel.onTabChanged(0);
}
});
@@ -85,6 +92,7 @@ class _MedicalFilePageState extends State {
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(
@@ -111,10 +119,7 @@ class _MedicalFilePageState extends State {
SizedBox(height: 16.h),
Container(
width: double.infinity,
- decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
- color: AppColors.whiteColor,
- borderRadius: 24,
- ),
+ decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24),
child: Padding(
padding: EdgeInsets.all(16.h),
child: Column(
@@ -123,11 +128,7 @@ class _MedicalFilePageState extends State {
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
- Image.asset(
- appState.getAuthenticatedUser()?.gender == 1 ? AppAssets.male_img : AppAssets.femaleImg,
- width: 56.h,
- height: 56.h,
- ),
+ 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,
@@ -768,4 +769,9 @@ class _MedicalFilePageState extends State {
return Container();
}
}
+
+ getMember() {
+ // AuthanticationViewModel authanticationViewModel = getIt.get();
+ // RequestUtils.getAddFamilyRequest(nationalIDorFile: nationalIDorFile, mobileNo: mobileNo, countryCode: countryCode, loginType: loginType);
+ }
}
diff --git a/lib/presentation/my_family/my_Family.dart b/lib/presentation/my_family/my_Family.dart
new file mode 100644
index 0000000..6e4ef91
--- /dev/null
+++ b/lib/presentation/my_family/my_Family.dart
@@ -0,0 +1,197 @@
+import 'package:easy_localization/easy_localization.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_svg/flutter_svg.dart';
+import 'package:hmg_patient_app_new/core/app_assets.dart';
+import 'package:hmg_patient_app_new/core/app_export.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/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/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/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';
+
+class FamilyMedicalScreen extends StatefulWidget {
+ final List profiles;
+ final Function(FamilyFileResponseModelLists) onSelect;
+
+ const FamilyMedicalScreen({
+ Key? key,
+ required this.profiles,
+ required this.onSelect,
+ }) : super(key: key);
+
+ @override
+ State createState() => _FamilyMedicalScreenState();
+}
+
+class _FamilyMedicalScreenState extends State {
+ List tabs = [CustomTabBarModel("", LocaleKeys.medicalFile.tr()), CustomTabBarModel("", LocaleKeys.request.tr())];
+
+ @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();
+ },
+ icon: AppAssets.add_icon,
+ height: 56.h,
+ fontWeight: FontWeight.w600,
+ )),
+ );
+ }
+
+ void showModelSheet() {
+ AuthenticationViewModel authVm = getIt.get();
+ return 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: () {});
+ }
+}
diff --git a/lib/presentation/my_family/widget/family_cards.dart b/lib/presentation/my_family/widget/family_cards.dart
new file mode 100644
index 0000000..480f91f
--- /dev/null
+++ b/lib/presentation/my_family/widget/family_cards.dart
@@ -0,0 +1,116 @@
+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/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/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/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';
+
+class FamilyCards extends StatefulWidget {
+ final List profiles;
+ final Function(FamilyFileResponseModelLists) onSelect;
+ final bool isShowDetails;
+ final bool isBottomSheet;
+
+ const FamilyCards({super.key, required this.profiles, required this.onSelect, this.isShowDetails = false, this.isBottomSheet = false});
+
+ @override
+ State createState() => _FamilyCardsState();
+}
+
+class _FamilyCardsState extends State {
+ AppState appState = getIt();
+
+ @override
+ Widget build(BuildContext context) {
+ return GridView.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,
+ ),
+ itemBuilder: (context, index) {
+ final profile = widget.profiles[index];
+ final isActive = (profile.responseId == appState
+ .getAuthenticatedUser()
+ ?.patientId);
+ return Container(
+ 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
+ child: Column(
+ mainAxisSize: MainAxisSize.min,
+ 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),
+ 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),
+ ],
+ ),
+ ),
+ );
+ },
+ );
+ }
+}
diff --git a/lib/presentation/my_family/widget/my_family_sheet.dart b/lib/presentation/my_family/widget/my_family_sheet.dart
new file mode 100644
index 0000000..a119906
--- /dev/null
+++ b/lib/presentation/my_family/widget/my_family_sheet.dart
@@ -0,0 +1,31 @@
+import 'package:flutter/material.dart';
+import 'package:hmg_patient_app_new/core/utils/utils.dart';
+import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
+import 'package:hmg_patient_app_new/features/medical_file/models/family_file_response_model.dart';
+import 'package:hmg_patient_app_new/presentation/my_family/my_Family.dart';
+import 'package:hmg_patient_app_new/presentation/my_family/widget/family_cards.dart';
+import 'package:hmg_patient_app_new/theme/colors.dart';
+import 'package:hmg_patient_app_new/widgets/common_bottom_sheet.dart';
+
+class MyFamilySheet {
+ static void show(BuildContext context, List familyLists, Function(FamilyFileResponseModelLists) onSelect) {
+ 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),
+ ],
+ ),
+ child: FamilyCards(
+ profiles: familyLists,
+ onSelect: (profile) {
+ Navigator.of(context).pop(); // Close the bottom sheet
+ onSelect(profile); // Call the onSelect callback
+ },
+ isBottomSheet: true),
+ callBackFunc: () {},
+ );
+ }
+}
diff --git a/lib/theme/colors.dart b/lib/theme/colors.dart
index 2627a12..06079dc 100644
--- a/lib/theme/colors.dart
+++ b/lib/theme/colors.dart
@@ -36,13 +36,15 @@ class AppColors {
static const Color warningColorYellow = Color(0xFFF4A308);
static const Color blackBgColor = Color(0xFF2E3039);
static const blackColor = textColor;
- static const inputLabelTextColor = Color(0xff898A8D);
- static const greyTextColor = Color(0xFF8F9AA3);
+ static const Color inputLabelTextColor = Color(0xff898A8D);
+ static const Color greyTextColor = Color(0xFF8F9AA3);
+ static const Color lightGrayBGColor = Color(0x142E3039);
static const lightGreenColor = Color(0xFF0ccedde);
static const textGreenColor = Color(0xFF18C273);
static const Color ratingColorYellow = Color(0xFFFFAF15);
+ static const Color spacerLineColor = Color(0x2E30391A);
//Chips
static const Color successColor = Color(0xff18C273);
@@ -51,6 +53,8 @@ class AppColors {
static const Color infoColor = Color(0xFF0B85F7);
static const Color warningColor = Color(0xFFFFCC00);
static const Color greyColor = Color(0xFFEFEFF0);
+ static const Color chipPrimaryRedBorderColor = Color(0xFFED1C2B);
+ static const Color chipSecondaryLightRedColor = Color(0xFFFEE9EA);
static const Color successLightColor = Color(0xFF18C273);
static const Color errorLightColor = Color(0xFFED1C2B);
diff --git a/lib/widgets/chip/custom_chip_widget.dart b/lib/widgets/chip/custom_chip_widget.dart
index 6c2f1e3..1d0b5ef 100644
--- a/lib/widgets/chip/custom_chip_widget.dart
+++ b/lib/widgets/chip/custom_chip_widget.dart
@@ -1,5 +1,6 @@
import 'package:flutter/material.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/utils.dart';
import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
import 'package:hmg_patient_app_new/extensions/widget_extensions.dart';
@@ -12,6 +13,10 @@ class CustomChipWidget extends StatelessWidget {
final bool isSelected;
final double borderRadius;
final EdgeInsetsGeometry padding;
+ final Color? backgroundColor;
+ final Color? textColor;
+ final Color? borderColor;
+ final bool isShowBorder;
const CustomChipWidget({
super.key,
@@ -22,6 +27,10 @@ class CustomChipWidget extends StatelessWidget {
this.isSelected = false,
this.borderRadius = 12,
this.padding = const EdgeInsets.all(8),
+ this.backgroundColor,
+ this.textColor,
+ this.borderColor,
+ this.isShowBorder = false,
});
@override
@@ -32,11 +41,13 @@ class CustomChipWidget extends StatelessWidget {
return Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(borderRadius),
- color: isSelected ? chipType.color : chipType.backgroundColor,
- border: Border.all(
- color: chipType.color,
- width: isSelected ? 0 : 1,
- ),
+ color: isSelected ? chipType.color : backgroundColor ?? chipType.backgroundColor,
+ border: isShowBorder
+ ? Border.all(
+ color: chipType.color,
+ width: isSelected ? 0 : 1,
+ )
+ : null,
),
child: InkWell(
onTap: hasOnTap ? onTap : null,
@@ -51,18 +62,9 @@ class CustomChipWidget extends StatelessWidget {
children: [
if (iconAsset != null) ...[
Utils.buildSvgWithAssets(icon: iconAsset!),
- const SizedBox(width: 6),
+ SizedBox(width: 4.h),
],
- Text(
- chipText.toUpperCase(),
- style: context.dynamicTextStyle(
- fontWeight: FontWeight.w500,
- fontSize: 14,
- color: isSelected ? Colors.white : chipType.color,
- letterSpacing: 0.1,
- isLanguageSwitcher: true,
- ),
- ),
+ chipText.toText10(isBold: true, color: isSelected ? Colors.white : textColor ?? chipType.color, maxlines: 1, weight: FontWeight.w500, letterSpacing: -0.5),
],
),
),
diff --git a/lib/widgets/my_family/my_Family.dart b/lib/widgets/my_family/my_Family.dart
deleted file mode 100644
index 912ae0b..0000000
--- a/lib/widgets/my_family/my_Family.dart
+++ /dev/null
@@ -1,44 +0,0 @@
-import 'package:flutter/material.dart';
-
-class ProfileSelector extends StatelessWidget {
- final List