diff --git a/assets/images/svg/alarm_clock_icon.svg b/assets/images/svg/alarm_clock_icon.svg
new file mode 100644
index 0000000..50b64bd
--- /dev/null
+++ b/assets/images/svg/alarm_clock_icon.svg
@@ -0,0 +1,5 @@
+
diff --git a/assets/images/svg/all_medications_icon.svg b/assets/images/svg/all_medications_icon.svg
new file mode 100644
index 0000000..3d3449b
--- /dev/null
+++ b/assets/images/svg/all_medications_icon.svg
@@ -0,0 +1,5 @@
+
diff --git a/assets/images/svg/allergy_info_icon.svg b/assets/images/svg/allergy_info_icon.svg
new file mode 100644
index 0000000..fc962cc
--- /dev/null
+++ b/assets/images/svg/allergy_info_icon.svg
@@ -0,0 +1,5 @@
+
diff --git a/assets/images/svg/email_icon.svg b/assets/images/svg/email_icon.svg
new file mode 100644
index 0000000..9e052e7
--- /dev/null
+++ b/assets/images/svg/email_icon.svg
@@ -0,0 +1,4 @@
+
diff --git a/assets/images/svg/forward_chevron_icon.svg b/assets/images/svg/forward_chevron_icon.svg
new file mode 100644
index 0000000..656d80e
--- /dev/null
+++ b/assets/images/svg/forward_chevron_icon.svg
@@ -0,0 +1,3 @@
+
diff --git a/assets/images/svg/my_account_icon.svg b/assets/images/svg/my_account_icon.svg
new file mode 100644
index 0000000..4bfe5b1
--- /dev/null
+++ b/assets/images/svg/my_account_icon.svg
@@ -0,0 +1,4 @@
+
diff --git a/assets/images/svg/notes_icon.svg b/assets/images/svg/notes_icon.svg
new file mode 100644
index 0000000..5d7ab0e
--- /dev/null
+++ b/assets/images/svg/notes_icon.svg
@@ -0,0 +1,9 @@
+
diff --git a/assets/images/svg/search_by_clinic_icon.svg b/assets/images/svg/search_by_clinic_icon.svg
new file mode 100644
index 0000000..ce00f8c
--- /dev/null
+++ b/assets/images/svg/search_by_clinic_icon.svg
@@ -0,0 +1,5 @@
+
diff --git a/assets/images/svg/search_by_doctor_icon.svg b/assets/images/svg/search_by_doctor_icon.svg
new file mode 100644
index 0000000..2ca5eb9
--- /dev/null
+++ b/assets/images/svg/search_by_doctor_icon.svg
@@ -0,0 +1,5 @@
+
diff --git a/assets/images/svg/search_by_region_icon.svg b/assets/images/svg/search_by_region_icon.svg
new file mode 100644
index 0000000..00abe12
--- /dev/null
+++ b/assets/images/svg/search_by_region_icon.svg
@@ -0,0 +1,5 @@
+
diff --git a/assets/images/svg/select_hospital_icon.svg b/assets/images/svg/select_hospital_icon.svg
new file mode 100644
index 0000000..ce00f8c
--- /dev/null
+++ b/assets/images/svg/select_hospital_icon.svg
@@ -0,0 +1,5 @@
+
diff --git a/assets/images/svg/vaccine_info_icon.svg b/assets/images/svg/vaccine_info_icon.svg
new file mode 100644
index 0000000..d8d22b2
--- /dev/null
+++ b/assets/images/svg/vaccine_info_icon.svg
@@ -0,0 +1,4 @@
+
diff --git a/assets/langs/ar-SA.json b/assets/langs/ar-SA.json
index 933afa4..bbfa68c 100644
--- a/assets/langs/ar-SA.json
+++ b/assets/langs/ar-SA.json
@@ -811,5 +811,8 @@
"allSet": "جاهز! الآن يمكنك تسجيل الدخول باستخدام Face ID / Biometric أو البصمة",
"enableQuickLogin":"تمكين تسجيل الدخول السريع",
"enableMsg":"تمكين تسجيل الدخول السريع سيسمح بالتحقق من خلال Face ID / Biometric الخاص بجهازك الحالي",
- "notNow": "ليس الآن"
+ "notNow": "ليس الآن",
+ "pendingActivation": "في انتظار التنشيط",
+ "awaitingApproval": "انتظر القبول",
+ "ready": "جاهز"
}
\ No newline at end of file
diff --git a/assets/langs/en-US.json b/assets/langs/en-US.json
index 0b29886..e054238 100644
--- a/assets/langs/en-US.json
+++ b/assets/langs/en-US.json
@@ -807,5 +807,8 @@
"allSet": "All Set! Now you can login with Face ID or Biometric",
"enableQuickLogin": "Enable Quick Login",
"enableMsg": "Enabling the quick login will verify through your existing device Face ID / Biometric",
- "notNow": "Not Now"
+ "notNow": "Not Now",
+ "pendingActivation": "Pending Activation",
+ "awaitingApproval": "Awaiting Approval",
+ "ready": "Ready"
}
\ No newline at end of file
diff --git a/lib/core/api/api_client.dart b/lib/core/api/api_client.dart
index 2fd8082..5e9dbb7 100644
--- a/lib/core/api/api_client.dart
+++ b/lib/core/api/api_client.dart
@@ -26,6 +26,7 @@ abstract class ApiClient {
bool isAllowAny,
bool isExternal,
bool isRCService,
+ bool isPaymentServices,
bool bypassConnectionCheck,
});
@@ -97,6 +98,7 @@ class ApiClientImp implements ApiClient {
bool isAllowAny = false,
bool isExternal = false,
bool isRCService = false,
+ bool isPaymentServices = false,
bool bypassConnectionCheck = false,
}) async {
String url;
@@ -204,7 +206,12 @@ class ApiClientImp implements ApiClient {
} else {
var parsed = json.decode(utf8.decode(response.bodyBytes));
if (isAllowAny) {
- onSuccess(parsed, statusCode, messageStatus: parsed['MessageStatus'], errorMessage: parsed['ErrorEndUserMessage']);
+ if (isPaymentServices) {
+ onSuccess(parsed, statusCode, messageStatus: 1, errorMessage: "");
+ } else {
+ onSuccess(parsed, statusCode,
+ messageStatus: parsed.contains('MessageStatus') ? parsed['MessageStatus'] : 1, errorMessage: parsed.contains('ErrorEndUserMessage') ? parsed['ErrorEndUserMessage'] : "");
+ }
} else {
if (parsed['Response_Message'] != null) {
onSuccess(parsed, statusCode, messageStatus: parsed['MessageStatus'], errorMessage: parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage']);
diff --git a/lib/core/api_consts.dart b/lib/core/api_consts.dart
index 1e22ded..bad2e4c 100644
--- a/lib/core/api_consts.dart
+++ b/lib/core/api_consts.dart
@@ -804,6 +804,7 @@ class ApiConsts {
static final String insertPatientMobileData = 'Services/MobileNotifications.svc/REST/Insert_PatientMobileDeviceInfo';
static final String getPatientMobileData = '/Services/Authentication.svc/REST/GetMobileLoginInfo';
static final String getPrivileges = 'Services/Patients.svc/REST/Service_Privilege';
+ static final String registerUser = 'Services/Authentication.svc/REST/PatientRegistration';
// 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 ffbbbee..9518fd9 100644
--- a/lib/core/app_assets.dart
+++ b/lib/core/app_assets.dart
@@ -95,7 +95,19 @@ class AppAssets {
static const String checkin_location_icon = '$svgBasePath/checkin_location_icon.svg';
static const String checkin_nfc_icon = '$svgBasePath/checkin_nfc_icon.svg';
static const String checkin_qr_icon = '$svgBasePath/checkin_qr_icon.svg';
+ static const String my_account_icon = '$svgBasePath/my_account_icon.svg';
+ static const String select_hospital_icon = '$svgBasePath/select_hospital_icon.svg';
+ static const String email_icon = '$svgBasePath/email_icon.svg';
+ static const String notes_icon = '$svgBasePath/notes_icon.svg';
+ static const String forward_chevron_icon = '$svgBasePath/forward_chevron_icon.svg';
static const String logout = '$svgBasePath/logout.svg';
+ static const String alarm_clock_icon = '$svgBasePath/alarm_clock_icon.svg';
+ static const String all_medications_icon = '$svgBasePath/all_medications_icon.svg';
+ static const String allergy_info_icon = '$svgBasePath/allergy_info_icon.svg';
+ static const String vaccine_info_icon = '$svgBasePath/vaccine_info_icon.svg';
+ static const String search_by_clinic_icon = '$svgBasePath/search_by_clinic_icon.svg';
+ static const String search_by_doctor_icon = '$svgBasePath/search_by_doctor_icon.svg';
+ static const String search_by_region_icon = '$svgBasePath/search_by_region_icon.svg';
//bottom navigation//
static const String homeBottom = '$svgBasePath/home_bottom.svg';
diff --git a/lib/core/app_state.dart b/lib/core/app_state.dart
index 3c4555e..52500bf 100644
--- a/lib/core/app_state.dart
+++ b/lib/core/app_state.dart
@@ -5,6 +5,7 @@ import 'package:hmg_patient_app_new/core/common_models/privilege/HMCProjectListM
import 'package:hmg_patient_app_new/core/common_models/privilege/PrivilegeModel.dart';
import 'package:hmg_patient_app_new/core/common_models/privilege/ProjectDetailListModel.dart';
import 'package:hmg_patient_app_new/core/common_models/privilege/VidaPlusProjectListModel.dart';
+import 'package:hmg_patient_app_new/features/authentication/models/request_models/send_activation_request_model.dart';
import 'package:hmg_patient_app_new/features/authentication/models/resp_models/authenticated_user_resp_model.dart';
import 'package:hmg_patient_app_new/features/authentication/models/resp_models/check_user_staus_nhic_response_model.dart';
import 'package:hmg_patient_app_new/features/authentication/models/resp_models/select_device_by_imei.dart';
diff --git a/lib/core/dependencies.dart b/lib/core/dependencies.dart
index 0afa53c..f86ec97 100644
--- a/lib/core/dependencies.dart
+++ b/lib/core/dependencies.dart
@@ -6,11 +6,16 @@ import 'package:hmg_patient_app_new/core/location_util.dart';
import 'package:hmg_patient_app_new/features/authentication/authentication_repo.dart';
import 'package:hmg_patient_app_new/features/authentication/authentication_view_model.dart';
import 'package:hmg_patient_app_new/features/book_appointments/book_appointments_repo.dart';
+import 'package:hmg_patient_app_new/features/book_appointments/book_appointments_view_model.dart';
import 'package:hmg_patient_app_new/features/common/common_repo.dart';
+import 'package:hmg_patient_app_new/features/habib_wallet/habib_wallet_repo.dart';
+import 'package:hmg_patient_app_new/features/habib_wallet/habib_wallet_view_model.dart';
import 'package:hmg_patient_app_new/features/insurance/insurance_repo.dart';
import 'package:hmg_patient_app_new/features/insurance/insurance_view_model.dart';
import 'package:hmg_patient_app_new/features/lab/lab_repo.dart';
import 'package:hmg_patient_app_new/features/lab/lab_view_model.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_repo.dart';
import 'package:hmg_patient_app_new/features/my_appointments/my_appointments_view_model.dart';
import 'package:hmg_patient_app_new/features/payfort/payfort_repo.dart';
@@ -85,6 +90,8 @@ class AppDependencies {
getIt.registerLazySingleton(() => InsuranceRepoImp(loggerService: getIt(), apiClient: getIt()));
getIt.registerLazySingleton(() => PayfortRepoImp(loggerService: getIt(), apiClient: getIt()));
getIt.registerLazySingleton(() => LocalAuthService(loggerService: getIt(), localAuth: getIt()));
+ getIt.registerLazySingleton(() => HabibWalletRepoImp(loggerService: getIt(), apiClient: getIt()));
+ getIt.registerLazySingleton(() => MedicalFileRepoImp(loggerService: getIt(), apiClient: getIt()));
// ViewModels
// Global/shared VMs → LazySingleton
@@ -125,24 +132,45 @@ class AppDependencies {
);
getIt.registerLazySingleton(
- () => PayfortViewModel(
+ () => PayfortViewModel(
payfortRepo: getIt(),
errorHandlerService: getIt(),
),
);
- getIt.registerLazySingleton(
- () => AuthenticationViewModel(
- authenticationRepo: getIt(),
- cacheService: getIt(),
- navigationService: getIt(),
- dialogService: getIt(),
- appState: getIt(),
+ getIt.registerLazySingleton(
+ () => HabibWalletViewModel(
+ habibWalletRepo: getIt(),
+ errorHandlerService: getIt(),
+ ),
+ );
+
+ getIt.registerLazySingleton(
+ () => HabibWalletViewModel(
+ habibWalletRepo: getIt(),
+ errorHandlerService: getIt(),
+ ),
+ );
+
+ getIt.registerLazySingleton(
+ () => MedicalFileViewModel(
+ medicalFileRepo: getIt(),
+ errorHandlerService: getIt(),
+ ),
+ );
+
+ getIt.registerLazySingleton(
+ () => BookAppointmentsViewModel(
+ bookAppointmentsRepo: getIt(),
errorHandlerService: getIt(),
- localAuthService: getIt()
),
);
+ getIt.registerLazySingleton(
+ () => AuthenticationViewModel(
+ authenticationRepo: getIt(), cacheService: getIt(), navigationService: getIt(), dialogService: getIt(), appState: getIt(), errorHandlerService: getIt(), localAuthService: getIt()),
+ );
+
// Screen-specific VMs → Factory
// getIt.registerFactory(
// () => BookAppointmentsViewModel(
diff --git a/lib/core/utils/request_utils.dart b/lib/core/utils/request_utils.dart
index f54432c..00bfc94 100644
--- a/lib/core/utils/request_utils.dart
+++ b/lib/core/utils/request_utils.dart
@@ -1,7 +1,12 @@
+import 'package:easy_localization/easy_localization.dart';
+import 'package:hijri_gregorian_calendar/hijri_gregorian_calendar.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/dependencies.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/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';
@@ -60,7 +65,7 @@ class RequestUtils {
required String? deviceToken,
required bool patientOutSA,
required String? loginTokenID,
- required var registeredData,
+ RegistrationDataModelPayload? registeredData,
int? patientId,
required String nationIdText,
required String countryCode,
@@ -80,9 +85,14 @@ class RequestUtils {
request.logInTokenID = loginTokenID ?? "";
if (registeredData != null) {
- request.searchType = registeredData.searchType ?? 1;
- request.patientID = registeredData.patientID ?? 0;
- request.patientIdentificationID = request.nationalID = registeredData.patientIdentificationID ?? '0';
+ //TODO: Issue Here if Not Signup
+ request.searchType = registeredData.searchType != null
+ ? registeredData.searchType
+ : fileNo
+ ? 1
+ : 2;
+ request.patientID = registeredData.patientId ?? 0;
+ request.patientIdentificationID = request.nationalID = (registeredData.patientIdentificationId ?? 0);
request.dob = registeredData.dob;
request.isRegister = registeredData.isRegister;
} else {
@@ -90,9 +100,11 @@ class RequestUtils {
request.patientID = patientId ?? int.parse(nationIdText);
request.patientIdentificationID = request.nationalID = 0;
request.searchType = 2;
+ //TODO: Issue HEre is Not Login
} else {
request.patientID = 0;
request.searchType = 1;
+ //TODO: Issue HEre is Not Login
request.patientIdentificationID = request.nationalID = (nationIdText.isNotEmpty ? int.parse(nationIdText) : 0);
}
request.isRegister = false;
@@ -132,9 +144,10 @@ class RequestUtils {
request.patientIdentificationID = request.nationalID = payload["PatientIdentificationID"] ?? '0';
request.dob = payload["DOB"];
request.isRegister = payload["isRegister"];
- request.healthId = _appState.getNHICUserData.healthId;
+ request.healthId = patientOutSA ? null : _appState.getNHICUserData.healthId;
request.isHijri = payload["IsHijri"];
request.deviceToken = _appState.deviceToken;
+ request.projectOutSA = patientOutSA;
} else {
request.searchType = isFileNo ? 2 : 1;
request.patientID = patientId ?? 0;
@@ -172,4 +185,65 @@ class RequestUtils {
request.tokenId = null;
return request;
}
+
+ static dynamic getUserSignupCompletionRequest({String? fullName, String? emailAddress, GenderTypeEnum? gender, MaritalStatusTypeEnum? maritalStatus}) {
+ AppState appState = getIt.get();
+
+ bool isDubai = appState.getUserRegistrationPayload.patientOutSa == 1 ? true : false;
+ List names = fullName != null ? fullName.split(" ") : [];
+
+ var dob = appState.getUserRegistrationPayload.dob;
+ final DateFormat dateFormat1 = DateFormat('MM/dd/yyyy');
+ final DateFormat dateFormat2 = DateFormat('dd/MM/yyyy');
+ DateTime gregorianDate = dateFormat2.parse(dob!);
+ HijriGregDate hijriDate = HijriGregConverter.gregorianToHijri(gregorianDate);
+ String? date = "${hijriDate.day}/${hijriDate.month}/${hijriDate.year}";
+
+ return {
+ "Patientobject": {
+ "TempValue": true,
+ "PatientIdentificationType":
+ (isDubai ? appState.getUserRegistrationPayload.patientIdentificationId?.toString().substring(0, 1) : appState.getNHICUserData.idNumber!.substring(0, 1)) == "1" ? 1 : 2,
+ "PatientIdentificationNo": isDubai ? appState.getUserRegistrationPayload.patientIdentificationId.toString() : appState.getNHICUserData.idNumber.toString(),
+ "MobileNumber": appState.getUserRegistrationPayload.patientMobileNumber ?? 0,
+ "PatientOutSA": (appState.getUserRegistrationPayload.zipCode == CountryEnum.saudiArabia.countryCode || appState.getUserRegistrationPayload.zipCode == '+966') ? 0 : 1,
+ "FirstNameN": isDubai ? "..." : appState.getNHICUserData.firstNameAr,
+ "FirstName": isDubai ? (names.isNotEmpty ? names[0] : "...") : appState.getNHICUserData.firstNameEn,
+ "MiddleNameN": isDubai ? "..." : appState.getNHICUserData.secondNameAr,
+ "MiddleName": isDubai ? "..." : appState.getNHICUserData.secondNameEn,
+ "LastNameN": isDubai ? "..." : appState.getNHICUserData.lastNameAr,
+ "LastName": isDubai ? (names.length > 1 ? names[1] : "...") : appState.getNHICUserData.lastNameEn,
+ "StrDateofBirth": dateFormat1.format(dateFormat2.parse(dob)),
+ "DateofBirth": DateUtil.convertISODateToJsonDate((dob ?? "").replaceAll('/', '-')),
+ "Gender": isDubai ? (gender == GenderTypeEnum.male ? 1 : 2) : (appState.getNHICUserData.gender == 'M' ? 1 : 2),
+ "NationalityID": isDubai ? "UAE" : appState.getNHICUserData.nationalityCode,
+ "eHealthIDField": isDubai ? null : appState.getNHICUserData.healthId,
+ "DateofBirthN": date,
+ "EmailAddress": emailAddress,
+ "SourceType": (appState.getUserRegistrationPayload.zipCode == CountryEnum.saudiArabia.countryCode || appState.getUserRegistrationPayload.zipCode == '+966') ? "1" : "2",
+ "PreferredLanguage": appState.getLanguageCode() == "ar" ? (isDubai ? "1" : 1) : (isDubai ? "2" : 2),
+ "Marital": isDubai
+ ? (maritalStatus == MaritalStatusTypeEnum.single
+ ? '0'
+ : maritalStatus == MaritalStatusTypeEnum.married
+ ? '1'
+ : '2')
+ : (appState.getNHICUserData.maritalStatusCode == 'U'
+ ? '0'
+ : appState.getNHICUserData.maritalStatusCode == 'M'
+ ? '1'
+ : '2'),
+ },
+ "PatientIdentificationID": isDubai ? appState.getUserRegistrationPayload.patientIdentificationId.toString() : appState.getNHICUserData.idNumber.toString(),
+ "PatientMobileNumber": appState.getUserRegistrationPayload.patientMobileNumber.toString()[0] == '0'
+ ? appState.getUserRegistrationPayload.patientMobileNumber
+ : '0${appState.getUserRegistrationPayload.patientMobileNumber}',
+ "DOB": dob,
+ "IsHijri": appState.getUserRegistrationPayload.isHijri,
+ "PatientOutSA": (appState.getUserRegistrationPayload.zipCode == CountryEnum.saudiArabia.countryCode || appState.getUserRegistrationPayload.zipCode == '+966') ? 0 : 1,
+ "isDentalAllowedBackend": appState.getUserRegistrationPayload.isDentalAllowedBackend,
+ "ZipCode": appState.getUserRegistrationPayload.zipCode,
+ if (!isDubai) "HealthId": appState.getNHICUserData.healthId,
+ };
+ }
}
diff --git a/lib/core/utils/utils.dart b/lib/core/utils/utils.dart
index ebb7037..e228591 100644
--- a/lib/core/utils/utils.dart
+++ b/lib/core/utils/utils.dart
@@ -1,5 +1,7 @@
import 'dart:convert';
import 'dart:developer';
+import 'dart:io';
+import 'dart:typed_data';
import 'package:connectivity_plus/connectivity_plus.dart';
import 'package:crypto/crypto.dart' as crypto;
@@ -21,6 +23,7 @@ import 'package:hmg_patient_app_new/theme/colors.dart';
import 'package:hmg_patient_app_new/widgets/dialogs/confirm_dialog.dart';
import 'package:hmg_patient_app_new/widgets/loading_dialog.dart';
import 'package:lottie/lottie.dart';
+import 'package:path_provider/path_provider.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'dart:math' as dartMath;
@@ -339,7 +342,8 @@ class Utils {
).center;
}
- static bool isVidaPlusProject(AppState appState, int projectID) {
+ static bool isVidaPlusProject(int projectID) {
+ AppState appState = getIt.get();
bool isVidaPlus = false;
for (var element in appState.vidaPlusProjectList) {
if (element.projectID == projectID) {
@@ -568,9 +572,10 @@ class Utils {
);
}
- static Widget getPaymentAmountWithSymbol(Widget paymentAmountWidget, Color iconColor, double iconSize, {bool isSaudiCurrency = true}) {
+ static Widget getPaymentAmountWithSymbol(Widget paymentAmountWidget, Color iconColor, double iconSize, {bool isSaudiCurrency = true, bool isExpanded = true}) {
return Row(
- mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ mainAxisAlignment: isExpanded ? MainAxisAlignment.spaceBetween : MainAxisAlignment.start,
+ crossAxisAlignment: CrossAxisAlignment.end,
children: [
appState.isArabic()
? Container()
@@ -628,4 +633,13 @@ class Utils {
static String getAdvancePaymentTransID(int projectID, int fileNumber) {
return '$projectID-$fileNumber-${DateTime.now().millisecondsSinceEpoch}';
}
+
+ static Future createFileFromString(String encodedStr, String ext) async {
+ Uint8List bytes = base64.decode(encodedStr);
+ String dir = (await getApplicationDocumentsDirectory()).path;
+ File file = File("$dir/" + DateTime.now().millisecondsSinceEpoch.toString() + "." + ext);
+ await file.writeAsBytes(bytes);
+ return file.path;
+ }
+
}
diff --git a/lib/features/authentication/authentication_repo.dart b/lib/features/authentication/authentication_repo.dart
index 8fbf259..f3f4119 100644
--- a/lib/features/authentication/authentication_repo.dart
+++ b/lib/features/authentication/authentication_repo.dart
@@ -32,6 +32,8 @@ abstract class AuthenticationRepo {
Future>> checkUserStatus({required dynamic commonAuthanticatedRequest});
+ Future>> registerUser({required dynamic registrationPayloadDataModelRequest});
+
Future>> insertPatientIMEIData({required dynamic patientIMEIDataRequest});
Future>> insertPatientDeviceData({required dynamic patientDeviceDataRequest});
@@ -184,7 +186,6 @@ class AuthenticationRepoImp implements AuthenticationRepo {
newRequest.projectOutSA = newRequest.zipCode == '966' ? false : true;
newRequest.isDentalAllowedBackend = false;
newRequest.forRegisteration = newRequest.isRegister ?? false;
-
newRequest.isRegister = false;
}
@@ -359,6 +360,39 @@ class AuthenticationRepoImp implements AuthenticationRepo {
}
}
+ @override
+ Future>> registerUser({required dynamic registrationPayloadDataModelRequest}) async {
+ try {
+ GenericApiModel? apiResponse;
+ Failure? failure;
+ await apiClient.post(
+ ApiConsts.registerUser,
+ body: registrationPayloadDataModelRequest,
+ 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> insertPatientIMEIData({required patientIMEIDataRequest}) {
try {
diff --git a/lib/features/authentication/authentication_view_model.dart b/lib/features/authentication/authentication_view_model.dart
index c82037f..b2464f6 100644
--- a/lib/features/authentication/authentication_view_model.dart
+++ b/lib/features/authentication/authentication_view_model.dart
@@ -15,6 +15,7 @@ import 'package:hmg_patient_app_new/core/utils/loading_utils.dart';
import 'package:hmg_patient_app_new/core/utils/request_utils.dart';
import 'package:hmg_patient_app_new/core/utils/utils.dart';
import 'package:hmg_patient_app_new/core/utils/validation_utils.dart';
+import 'package:hmg_patient_app_new/extensions/context_extensions.dart';
import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
import 'package:hmg_patient_app_new/features/authentication/authentication_repo.dart';
import 'package:hmg_patient_app_new/features/authentication/models/request_models/check_activation_code_register_request_model.dart';
@@ -31,6 +32,7 @@ import 'package:hmg_patient_app_new/services/error_handler_service.dart';
import 'package:hmg_patient_app_new/services/localauth_service.dart';
import 'package:hmg_patient_app_new/services/navigation_service.dart';
import 'package:hmg_patient_app_new/widgets/loader/bottomsheet_loader.dart';
+import 'package:hmg_patient_app_new/widgets/bottomsheet/exception_bottom_sheet.dart';
import 'models/request_models/get_user_mobile_device_data.dart';
import 'models/request_models/insert_patient_mobile_deviceinfo.dart';
@@ -80,7 +82,7 @@ class AuthenticationViewModel extends ChangeNotifier {
String errorMsg = '';
final FocusNode myFocusNode = FocusNode();
var healthId;
- int getDeviceLastLogin =1;
+ int getDeviceLastLogin = 1;
Future onLoginPressed() async {
try {
@@ -110,6 +112,8 @@ class AuthenticationViewModel extends ChangeNotifier {
isTermsAccepted = false;
selectedCountrySignup = CountryEnum.saudiArabia;
pickedCountryByUAEUser = null;
+ _appState.setUserRegistrationPayload = RegistrationDataModelPayload();
+ _appState.setNHICUserData = CheckUserStatusResponseNHIC();
}
void onCountryChange(CountryEnum country) {
@@ -191,7 +195,7 @@ class AuthenticationViewModel extends ChangeNotifier {
(failure) async {
// LoadingUtils.hideFullScreenLoader();
// await _errorHandlerService.handleError(failure: failure);
- LoadingUtils.hideFullScreenLoader();
+ LoaderBottomSheet.hideLoader();
_navigationService.pushPage(page: LoginScreen());
},
(apiResponse) {
@@ -238,6 +242,7 @@ class AuthenticationViewModel extends ChangeNotifier {
_navigationService.pushPage(page: SavedLogin());
// _navigationService.pushPage(page: LoginScreen());
} else {
+ print("print login........");
LoaderBottomSheet.hideLoader();
_navigationService.pushPage(page: LoginScreen());
}
@@ -292,12 +297,7 @@ class AuthenticationViewModel extends ChangeNotifier {
} else if (apiResponse.messageStatus == 1) {
if (apiResponse.data['isSMSSent']) {
_appState.setAppAuthToken = apiResponse.data['LogInTokenID'];
- await sendActivationCode(
- otpTypeEnum: otpTypeEnum,
- phoneNumber: phoneNumberController.text,
- nationalIdOrFileNumber: nationalIdController.text,
- );
-
+ await sendActivationCode(otpTypeEnum: otpTypeEnum, phoneNumber: phoneNumberController.text, nationalIdOrFileNumber: nationalIdController.text, isForRegister: false);
} else {
if (apiResponse.data['IsAuthenticated']) {
await checkActivationCode(
@@ -305,7 +305,6 @@ class AuthenticationViewModel extends ChangeNotifier {
onWrongActivationCode: (String? message) {},
activationCode: null, //todo silent login case halded on the repo itself..
);
-
}
}
}
@@ -313,41 +312,33 @@ class AuthenticationViewModel extends ChangeNotifier {
);
}
- Future sendActivationCode({required OTPTypeEnum otpTypeEnum, required String nationalIdOrFileNumber, required String phoneNumber, dynamic payload}) async {
- bool isForRegister = checkIsUserComingForRegister(request: payload);
- bool isPatientOutSA = isPatientOutsideSA(request: payload);
- bool isFileNo = isPatientHasFile(request: payload);
-
+ Future sendActivationCode({required OTPTypeEnum otpTypeEnum, required String nationalIdOrFileNumber, required String phoneNumber, required bool isForRegister, dynamic payload}) async {
var request = RequestUtils.getCommonRequestSendActivationCode(
- otpTypeEnum: otpTypeEnum,
- mobileNumber: phoneNumber,
- selectedLoginType: otpTypeEnum.toInt(),
- zipCode: selectedCountrySignup.countryCode,
- nationalId: int.parse(nationalIdOrFileNumber),
- isFileNo: isFileNo,
- patientId: 0,
- isForRegister: isForRegister,
- patientOutSA: isPatientOutSA,
- 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
+ ? false
+ : true,
+ payload: payload,
+ );
// TODO: GET APP SMS SIGNATURE HERE
request.sMSSignature = "enKTDcqbOVd";
- // GifLoaderDialogUtils.showMyDialog(context);
- // bool isForRegister = healthId != null || isDubai;
- // if (isForRegister) {
- // if (!isDubai) {
- // request.dob = dob; //isHijri == 1 ? dob : dateFormat2.format(dateFormat.parse(dob));
- // }
- // request.healthId = healthId;
- // request.isHijri = calenderType.toInt;
- // } else {
- // // request.dob = "";
- // // request.healthId = "";
- // // request.isHijri = 0;
- // }
+ if (checkIsUserComingForRegister(request: payload)) {
+ _appState.setUserRegistrationPayload = RegistrationDataModelPayload.fromJson(payload);
+ print("====== Demo ==========");
+ }
- final resultEither = await _authenticationRepo.sendActivationCodeRepo(sendActivationCodeReq: request, isRegister: isForRegister, languageID: 'er');
+ final resultEither = await _authenticationRepo.sendActivationCodeRepo(sendActivationCodeReq: request, isRegister: checkIsUserComingForRegister(request: payload), languageID: 'er');
resultEither.fold(
(failure) async => await _errorHandlerService.handleError(failure: failure),
@@ -381,23 +372,43 @@ class AuthenticationViewModel extends ChangeNotifier {
required OTPTypeEnum otpTypeEnum,
required Function(String? message) onWrongActivationCode,
}) async {
+ bool isForRegister = (_appState.getUserRegistrationPayload.healthId != null || _appState.getUserRegistrationPayload.patientOutSa == true);
+
final request = RequestUtils.getCommonRequestWelcome(
phoneNumber: phoneNumberController.text,
otpTypeEnum: otpTypeEnum,
deviceToken: _appState.deviceToken,
- patientOutSA: true,
+ // patientOutSA: _appState.getUserRegistrationPayload.projectOutSa == 1 ? true : false,
+ patientOutSA: isForRegister
+ ? _appState.getUserRegistrationPayload.projectOutSa == 1
+ ? true
+ : false
+ : _appState.getSelectDeviceByImeiRespModelElement != null
+ ? _appState.getSelectDeviceByImeiRespModelElement!.outSa!
+ : selectedCountrySignup == CountryEnum.saudiArabia
+ ? false
+ : true,
loginTokenID: _appState.appAuthToken,
- registeredData: null,
+ registeredData: isForRegister ? _appState.getUserRegistrationPayload : null,
nationIdText: nationalIdController.text,
countryCode: selectedCountrySignup.countryCode,
loginType: loginTypeEnum.toInt)
.toJson();
- LoaderBottomSheet.showLoader();
- bool isForRegister = (_appState.getUserRegistrationPayload.healthId != null || _appState.getUserRegistrationPayload.patientOutSa == true);
+ LoaderBottomSheet.showLoader();
if (isForRegister) {
- if (_appState.getUserRegistrationPayload.patientOutSa == true) request['DOB'] = _appState.getUserRegistrationPayload.dob;
+ if (_appState.getUserRegistrationPayload.patientOutSa == 0) request['DOB'] = _appState.getUserRegistrationPayload.dob;
request['HealthId'] = _appState.getUserRegistrationPayload.healthId;
request['IsHijri'] = _appState.getUserRegistrationPayload.isHijri;
+ request["PatientOutSA"] = _appState.getUserRegistrationPayload.projectOutSa == true ? 1 : 0;
+ request["ForRegisteration"] = _appState.getUserRegistrationPayload.isRegister;
+ request["isRegister"] = false;
+
+ // if (request.containsKey("OTP_SendType")) {
+ // request.remove("OTP_SendType");
+ // print("====== Demo: Removed OTP_SendType for Register state");
+ // }
+
+ print("====== Req");
final resultEither = await _authenticationRepo.checkActivationCodeRepo(newRequest: request, activationCode: activationCode.toString(), isRegister: true);
@@ -423,7 +434,6 @@ class AuthenticationViewModel extends ChangeNotifier {
resultEither.fold((failure) async => await _errorHandlerService.handleError(failure: failure), (apiResponse) async {
final activation = CheckActivationCode.fromJson(apiResponse.data as Map);
-
if (activation.errorCode == '699') {
// Todo: Hide Loader
// GifLoaderDialogUtils.hideDialog(context);
@@ -441,7 +451,6 @@ 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);
}
@@ -451,8 +460,9 @@ class AuthenticationViewModel extends ChangeNotifier {
bool isUserAgreedBefore = await checkIfUserAgreedBefore(request: request);
//updating the last login type in app state to show the fingerprint/face id option on home screen
- _appState.getSelectDeviceByImeiRespModelElement!.logInType = loginTypeEnum.toInt;
-
+ if (_appState.getSelectDeviceByImeiRespModelElement != null) {
+ _appState.getSelectDeviceByImeiRespModelElement!.logInType = loginTypeEnum.toInt;
+ }
LoaderBottomSheet.hideLoader();
insertPatientIMEIData(loginTypeEnum.toInt);
clearDefaultInputValues();
@@ -548,12 +558,12 @@ class AuthenticationViewModel extends ChangeNotifier {
loginTypeEnum = (_appState.deviceTypeID == 1 ? LoginTypeEnum.face : LoginTypeEnum.fingerprint);
if (!_appState.isAuthenticated) {
//commenting this api to check either the same flow working or not because this api does not needed further if work fine we will remove this
- // await getPatientDeviceData(loginTypeEnum.toInt);
+ // await getPatientDeviceData(loginTypeEnum.toInt);
await checkActivationCode(otpTypeEnum: OTPTypeEnum.faceIDFingerprint, activationCode: null, onWrongActivationCode: (String? message) {});
- await insertPatientIMEIData(loginTypeEnum.toInt);
+ await insertPatientIMEIData(loginTypeEnum.toInt);
} else {
// authenticated = true;
- await insertPatientIMEIData(loginTypeEnum.toInt);
+ await insertPatientIMEIData(loginTypeEnum.toInt);
}
LoaderBottomSheet.hideLoader();
notifyListeners();
@@ -615,35 +625,63 @@ class AuthenticationViewModel extends ChangeNotifier {
}
Future onRegistrationComplete() async {
- // if (emailAddress.text.isEmpty) {
- // Utils.showErrorToast(TranslationBase.of(context).enterEmailAddress);
- // return;
- // } else {
- // Navigator.of(context).pop();
- // registerNow();
- // }
- //authVM!.clearDefaultInputValues();
+ var request = RequestUtils.getUserSignupCompletionRequest(fullName: nameController.text, emailAddress: emailController.text, gender: genderType, maritalStatus: maritalStatus);
+ //
+ print("============= Final Payload ===============");
+ print(request);
+ print("=================== ====================");
+
+ final resultEither = await _authenticationRepo.registerUser(registrationPayloadDataModelRequest: request);
+ resultEither.fold((failure) async => await _errorHandlerService.handleError(failure: failure), (apiResponse) async {
+ if (apiResponse.data is String) {
+ //TODO: Here We Need to Show a Dialog Of Something in the case of Fail With OK and Cancel and the Display Variable WIll be result.
+ } else {
+ print(apiResponse.data as Map);
+ if (apiResponse.data["MessageStatus"] == 1) {
+ //TODO: Here We Need to Show a Dialog Of Something in the case of Success.
+ clearDefaultInputValues(); // This will Clear All Default Values Of User.
+ _navigationService.pushAndReplace(AppRoutes.loginScreen);
+ }
+ }
+ });
+
+ return;
}
Future checkUserStatusForRegistration({required dynamic response, required dynamic request}) async {
if (response is Map) {
- _appState.setAppAuthToken = response["LogInTokenID"];
if (response["MessageStatus"] == 2) {
print(response["ErrorEndUserMessage"]);
return;
}
if (response['hasFile'] == true) {
//TODO: Show Here Ok And Cancel Dialog and On OKPress it will go for sendActivationCode
+
+ _navigationService.context?.showBottomSheet(
+ child: ExceptionBottomSheet(
+ message: response["ErrorMessage"],
+ showCancel: true,
+ showOKButton: true,
+ onOkPressed: () {
+ _navigationService.popUntilNamed(AppRoutes.loginScreen);
+ },
+ onCancelPressed: () {
+ _navigationService.pop();
+ },
+ ));
} else {
request['forRegister'] = true;
request['isRegister'] = true;
+ _appState.setAppAuthToken = response['LogInTokenID'];
if (isPatientOutsideSA(request: response)) {
print("=======OUT SA=======");
- _appState.setAppAuthToken = response['LogInTokenID'];
sendActivationCode(
- otpTypeEnum: OTPTypeEnumExtension.fromInt(request["OTP_SendType"]),
- nationalIdOrFileNumber: request["PatientIdentificationID"].toString(),
- phoneNumber: request["PatientMobileNumber"].toString());
+ otpTypeEnum: OTPTypeEnumExtension.fromInt(request["OTP_SendType"]),
+ nationalIdOrFileNumber: request["PatientIdentificationID"].toString(),
+ phoneNumber: request["PatientMobileNumber"].toString(),
+ payload: request,
+ isForRegister: true,
+ );
} else {
print("=======IN SA=======");
chekUserNHICData(request: request);
@@ -657,13 +695,12 @@ class AuthenticationViewModel extends ChangeNotifier {
bool isPatientOutsideSA({required dynamic request}) {
bool isOutSideSa = false;
- if (request is Map && request.containsKey("PatientOutSA")) {
- if (request["PatientOutSA"] == true) {
- isOutSideSa = true;
- } else {
- isOutSideSa = false;
- }
+ if (request["PatientOutSA"] == true || request["PatientOutSA"] == 1) {
+ isOutSideSa = true;
+ } else {
+ isOutSideSa = false;
}
+
print(isOutSideSa);
return isOutSideSa;
}
@@ -682,10 +719,12 @@ class AuthenticationViewModel extends ChangeNotifier {
if (apiResponse.data is Map) {
setNHICData(apiResponse.data, request);
sendActivationCode(
- otpTypeEnum: OTPTypeEnumExtension.fromInt(request["OTP_SendType"]),
- nationalIdOrFileNumber: request["PatientIdentificationID"].toString(),
- phoneNumber: request["PatientMobileNumber"].toString(),
- payload: request);
+ otpTypeEnum: OTPTypeEnumExtension.fromInt(request["OTP_SendType"]),
+ nationalIdOrFileNumber: request["PatientIdentificationID"].toString(),
+ phoneNumber: request["PatientMobileNumber"].toString(),
+ payload: request,
+ isForRegister: true,
+ );
}
});
@@ -738,6 +777,7 @@ class AuthenticationViewModel extends ChangeNotifier {
deviceTypeId: _appState.getDeviceTypeID(),
patientId: _appState.getAuthenticatedUser()!.patientId!,
patientIdentificationNo: _appState.getAuthenticatedUser()!.patientIdentificationNo!,
+ identificationNo: _appState.getAuthenticatedUser()!.patientIdentificationNo!,
firstName: _appState.getAuthenticatedUser()!.firstName!,
lastName: _appState.getAuthenticatedUser()!.lastName!,
patientTypeId: _appState.getAuthenticatedUser()!.patientType,
@@ -784,33 +824,30 @@ class AuthenticationViewModel extends ChangeNotifier {
log("Insert IMEI Failed");
}
});
-
}
-
Future getPatientDeviceData(int loginType) async {
final resultEither = await _authenticationRepo.getPatientDeviceData(
patientDeviceDataRequest: GetUserMobileDeviceData(
- deviceToken: _appState.deviceToken,
- deviceTypeId: _appState.getDeviceTypeID(),
- patientId: _appState.getSelectDeviceByImeiRespModelElement!.patientId!,
- patientType: _appState.getSelectDeviceByImeiRespModelElement!.patientType,
- patientOutSa:_appState.getSelectDeviceByImeiRespModelElement!.outSa == true ?1 :0,
- loginType: loginType,
- languageId: _appState.getLanguageID(),
- latitude: _appState.userLat,
- longitude: _appState.userLong,
- mobileNo:_appState.getSelectDeviceByImeiRespModelElement!.mobile! ,
- patientMobileNumber:int.parse(_appState.getSelectDeviceByImeiRespModelElement!.mobile!),
- nationalId:_appState.getSelectDeviceByImeiRespModelElement!.identificationNo)
+ deviceToken: _appState.deviceToken,
+ deviceTypeId: _appState.getDeviceTypeID(),
+ patientId: _appState.getSelectDeviceByImeiRespModelElement!.patientId!,
+ patientType: _appState.getSelectDeviceByImeiRespModelElement!.patientType,
+ patientOutSa: _appState.getSelectDeviceByImeiRespModelElement!.outSa == true ? 1 : 0,
+ loginType: loginType,
+ languageId: _appState.getLanguageID(),
+ latitude: _appState.userLat,
+ longitude: _appState.userLong,
+ mobileNo: _appState.getSelectDeviceByImeiRespModelElement!.mobile!,
+ patientMobileNumber: int.parse(_appState.getSelectDeviceByImeiRespModelElement!.mobile!),
+ nationalId: _appState.getSelectDeviceByImeiRespModelElement!.identificationNo)
.toJson());
resultEither.fold((failure) async => await _errorHandlerService.handleError(failure: failure), (apiResponse) async {
if (apiResponse.messageStatus == 1) {
- dynamic deviceInfo= apiResponse.data['List_MobileLoginInfo'];
- getDeviceLastLogin = deviceInfo['LoginType'];
+ dynamic deviceInfo = apiResponse.data['List_MobileLoginInfo'];
+ getDeviceLastLogin = deviceInfo['LoginType'];
}
});
-
}
@override
diff --git a/lib/features/authentication/models/request_models/registration_payload_model.dart b/lib/features/authentication/models/request_models/registration_payload_model.dart
index fa4f612..bbb31f9 100644
--- a/lib/features/authentication/models/request_models/registration_payload_model.dart
+++ b/lib/features/authentication/models/request_models/registration_payload_model.dart
@@ -1,34 +1,170 @@
+// import 'dart:convert';
+//
+// import 'package:hmg_patient_app_new/core/enums.dart';
+//
+// class RegistrationDataModelPayload {
+// int? patientMobileNumber;
+// String? zipCode;
+// int? searchType;
+// int? patientId;
+// int? patientIdentificationId;
+// int? otpSendType;
+// int? patientOutSa;
+// bool? isDentalAllowedBackend;
+// String? dob;
+// int? isHijri;
+// bool? forRegister;
+// bool? isRegister;
+// String? healthId;
+// String? emailAddress;
+// String? nationalityCode;
+// GenderTypeEnum? gender;
+// MaritalStatusTypeEnum? maritalStatus;
+// String? fullName;
+//
+// RegistrationDataModelPayload({
+// this.patientMobileNumber,
+// this.zipCode,
+// this.searchType,
+// this.patientId,
+// this.patientIdentificationId,
+// this.otpSendType,
+// this.patientOutSa,
+// this.isDentalAllowedBackend,
+// this.dob,
+// this.isHijri,
+// this.forRegister,
+// this.isRegister,
+// this.healthId,
+// this.emailAddress,
+// this.nationalityCode,
+// this.gender,
+// this.maritalStatus,
+// this.fullName,
+// });
+//
+// factory RegistrationDataModelPayload.fromRawJson(String str) => RegistrationDataModelPayload.fromJson(json.decode(str));
+//
+// String toRawJson() => json.encode(toJson());
+//
+// factory RegistrationDataModelPayload.fromJson(Map json) => RegistrationDataModelPayload(
+// patientMobileNumber: json["PatientMobileNumber"],
+// zipCode: json["ZipCode"],
+// searchType: json["SearchType"],
+// patientId: json["PatientID"],
+// patientIdentificationId: json["PatientIdentificationID"],
+// otpSendType: json["OTP_SendType"],
+// patientOutSa: json["PatientOutSA"],
+// isDentalAllowedBackend: json["isDentalAllowedBackend"],
+// dob: json["DOB"],
+// isHijri: json["IsHijri"],
+// forRegister: json["forRegister"],
+// isRegister: json["isRegister"],
+// healthId: json["healthId"],
+// emailAddress: json["emailAddress"],
+// nationalityCode: json["nationalityCode"],
+// gender: json["gender"],
+// maritalStatus: json["maritalStatus"],
+// fullName: json["fullName"],
+// );
+//
+// Map toJson() => {
+// "PatientMobileNumber": patientMobileNumber,
+// "ZipCode": zipCode,
+// "SearchType": searchType,
+// "PatientID": patientId,
+// "PatientIdentificationID": patientIdentificationId,
+// "OTP_SendType": otpSendType,
+// "PatientOutSA": patientOutSa,
+// "isDentalAllowedBackend": isDentalAllowedBackend,
+// "DOB": dob,
+// "IsHijri": isHijri,
+// "forRegister": forRegister,
+// "isRegister": isRegister,
+// "healthId": healthId,
+// "emailAddress": emailAddress,
+// "nationalityCode": nationalityCode,
+// "gender": gender,
+// "maritalStatus": maritalStatus,
+// "fullName": fullName,
+// };
+// }
+
+
import 'dart:convert';
+import 'package:hmg_patient_app_new/core/enums.dart';
+
class RegistrationDataModelPayload {
int? patientMobileNumber;
+ String? mobileNo;
+ String? deviceToken;
+ bool? projectOutSa;
+ int? loginType;
String? zipCode;
+ bool? isRegister;
+ String? logInTokenId;
int? searchType;
int? patientId;
+ int? nationalId;
int? patientIdentificationId;
int? otpSendType;
+ String? languageId;
+ String? versionId;
+ String? channel;
+ String? ipAdress;
+ String? generalid;
int? patientOutSa;
bool? isDentalAllowedBackend;
+ String? deviceTypeId;
+ String? smsSignature;
String? dob;
int? isHijri;
- bool? forRegister;
- bool? isRegister;
+ String? patientType;
+ String? latitude;
+ String? longitude;
String? healthId;
+ String? emailAddress;
+ String? nationalityCode;
+ GenderTypeEnum? gender;
+ MaritalStatusTypeEnum? maritalStatus;
+ String? fullName;
+
RegistrationDataModelPayload({
this.patientMobileNumber,
+ this.mobileNo,
+ this.deviceToken,
+ this.projectOutSa,
+ this.loginType,
this.zipCode,
+ this.isRegister,
+ this.logInTokenId,
this.searchType,
this.patientId,
+ this.nationalId,
this.patientIdentificationId,
this.otpSendType,
+ this.languageId,
+ this.versionId,
+ this.channel,
+ this.ipAdress,
+ this.generalid,
this.patientOutSa,
this.isDentalAllowedBackend,
+ this.deviceTypeId,
+ this.smsSignature,
this.dob,
this.isHijri,
- this.forRegister,
- this.isRegister,
+ this.patientType,
+ this.latitude,
+ this.longitude,
this.healthId,
+ this.emailAddress,
+ this.nationalityCode,
+ this.gender,
+ this.maritalStatus,
+ this.fullName,
});
factory RegistrationDataModelPayload.fromRawJson(String str) => RegistrationDataModelPayload.fromJson(json.decode(str));
@@ -36,34 +172,74 @@ class RegistrationDataModelPayload {
String toRawJson() => json.encode(toJson());
factory RegistrationDataModelPayload.fromJson(Map json) => RegistrationDataModelPayload(
- patientMobileNumber: json["PatientMobileNumber"],
- zipCode: json["ZipCode"],
- searchType: json["SearchType"],
- patientId: json["PatientID"],
- patientIdentificationId: json["PatientIdentificationID"],
- otpSendType: json["OTP_SendType"],
- patientOutSa: json["PatientOutSA"],
- isDentalAllowedBackend: json["isDentalAllowedBackend"],
- dob: json["DOB"],
- isHijri: json["IsHijri"],
- forRegister: json["forRegister"],
- isRegister: json["isRegister"],
- healthId: json["healthId"],
- );
+ patientMobileNumber: json["PatientMobileNumber"],
+ mobileNo: json["MobileNo"],
+ deviceToken: json["DeviceToken"],
+ projectOutSa: json["ProjectOutSA"],
+ loginType: json["LoginType"],
+ zipCode: json["ZipCode"],
+ isRegister: json["isRegister"],
+ logInTokenId: json["LogInTokenID"],
+ searchType: json["SearchType"],
+ patientId: json["PatientID"],
+ nationalId: json["NationalID"],
+ patientIdentificationId: json["PatientIdentificationID"],
+ otpSendType: json["OTP_SendType"],
+ languageId: json["LanguageID"],
+ versionId: json["VersionID"],
+ channel: json["Channel"],
+ ipAdress: json["IPAdress"],
+ generalid: json["generalid"],
+ patientOutSa: json["PatientOutSA"],
+ isDentalAllowedBackend: json["isDentalAllowedBackend"],
+ deviceTypeId: json["DeviceTypeID"],
+ smsSignature: json["SMSSignature"],
+ dob: json["DOB"],
+ isHijri: json["IsHijri"],
+ patientType: json["PatientType"],
+ latitude: json["Latitude"],
+ longitude: json["Longitude"],
+ healthId: json["healthId"],
+ emailAddress: json["emailAddress"],
+ nationalityCode: json["nationalityCode"],
+ gender: json["gender"],
+ maritalStatus: json["maritalStatus"],
+ fullName: json["fullName"],
+ );
Map toJson() => {
- "PatientMobileNumber": patientMobileNumber,
- "ZipCode": zipCode,
- "SearchType": searchType,
- "PatientID": patientId,
- "PatientIdentificationID": patientIdentificationId,
- "OTP_SendType": otpSendType,
- "PatientOutSA": patientOutSa,
- "isDentalAllowedBackend": isDentalAllowedBackend,
- "DOB": dob,
- "IsHijri": isHijri,
- "forRegister": forRegister,
- "isRegister": isRegister,
- "healthId": healthId,
- };
+ "PatientMobileNumber": patientMobileNumber,
+ "MobileNo": mobileNo,
+ "DeviceToken": deviceToken,
+ "ProjectOutSA": projectOutSa,
+ "LoginType": loginType,
+ "ZipCode": zipCode,
+ "isRegister": isRegister,
+ "LogInTokenID": logInTokenId,
+ "SearchType": searchType,
+ "PatientID": patientId,
+ "NationalID": nationalId,
+ "PatientIdentificationID": patientIdentificationId,
+ "OTP_SendType": otpSendType,
+ "LanguageID": languageId,
+ "VersionID": versionId,
+ "Channel": channel,
+ "IPAdress": ipAdress,
+ "generalid": generalid,
+ "PatientOutSA": patientOutSa,
+ "isDentalAllowedBackend": isDentalAllowedBackend,
+ "DeviceTypeID": deviceTypeId,
+ "SMSSignature": smsSignature,
+ "DOB": dob,
+ "IsHijri": isHijri,
+ "PatientType": patientType,
+ "Latitude": latitude,
+ "Longitude": longitude,
+ "healthId": healthId,
+ "emailAddress": emailAddress,
+ "nationalityCode": nationalityCode,
+ "gender": gender,
+ "maritalStatus": maritalStatus,
+ "fullName": fullName,
+ };
}
diff --git a/lib/features/book_appointments/book_appointments_view_model.dart b/lib/features/book_appointments/book_appointments_view_model.dart
index e69de29..8f096dd 100644
--- a/lib/features/book_appointments/book_appointments_view_model.dart
+++ b/lib/features/book_appointments/book_appointments_view_model.dart
@@ -0,0 +1,17 @@
+import 'package:flutter/material.dart';
+import 'package:hmg_patient_app_new/features/book_appointments/book_appointments_repo.dart';
+import 'package:hmg_patient_app_new/services/error_handler_service.dart';
+
+class BookAppointmentsViewModel extends ChangeNotifier {
+ int selectedTabIndex = 0;
+
+ BookAppointmentsRepo bookAppointmentsRepo;
+ ErrorHandlerService errorHandlerService;
+
+ BookAppointmentsViewModel({required this.bookAppointmentsRepo, required this.errorHandlerService});
+
+ void onTabChanged(int index) {
+ selectedTabIndex = index;
+ notifyListeners();
+ }
+}
diff --git a/lib/features/habib_wallet/habib_wallet_repo.dart b/lib/features/habib_wallet/habib_wallet_repo.dart
new file mode 100644
index 0000000..5f47f6c
--- /dev/null
+++ b/lib/features/habib_wallet/habib_wallet_repo.dart
@@ -0,0 +1,58 @@
+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/common_models/generic_api_model.dart';
+import 'package:hmg_patient_app_new/core/exceptions/api_failure.dart';
+import 'package:hmg_patient_app_new/services/logger_service.dart';
+
+abstract class HabibWalletRepo {
+ Future>> getPatientBalanceAmount();
+}
+
+class HabibWalletRepoImp implements HabibWalletRepo {
+ final ApiClient apiClient;
+ final LoggerService loggerService;
+
+ HabibWalletRepoImp({required this.loggerService, required this.apiClient});
+
+ @override
+ Future>> getPatientBalanceAmount() async {
+ Map mapDevice = {};
+
+ try {
+ GenericApiModel? apiResponse;
+ Failure? failure;
+ await apiClient.post(
+ GET_PATIENT_AdVANCE_BALANCE_AMOUNT,
+ body: mapDevice,
+ onFailure: (error, statusCode, {messageStatus, failureType}) {
+ failure = failureType;
+ },
+ onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
+ try {
+ // final list = response['ListPLO'];
+ // if (list == null || list.isEmpty) {
+ // throw Exception("lab list is empty");
+ // }
+
+ // final labOrders = list.map((item) => PatientLabOrdersResponseModel.fromJson(item as Map)).toList().cast();
+
+ apiResponse = GenericApiModel(
+ messageStatus: messageStatus,
+ statusCode: statusCode,
+ errorMessage: null,
+ data: response["TotalAdvanceBalanceAmount"],
+ );
+ } 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/habib_wallet/habib_wallet_view_model.dart b/lib/features/habib_wallet/habib_wallet_view_model.dart
new file mode 100644
index 0000000..8e4fc26
--- /dev/null
+++ b/lib/features/habib_wallet/habib_wallet_view_model.dart
@@ -0,0 +1,39 @@
+import 'package:flutter/material.dart';
+import 'package:hmg_patient_app_new/features/habib_wallet/habib_wallet_repo.dart';
+import 'package:hmg_patient_app_new/services/error_handler_service.dart';
+
+class HabibWalletViewModel extends ChangeNotifier {
+ bool isWalletAmountLoading = false;
+ num habibWalletAmount = 0;
+
+ HabibWalletRepo habibWalletRepo;
+ ErrorHandlerService errorHandlerService;
+
+ HabibWalletViewModel({required this.habibWalletRepo, required this.errorHandlerService});
+
+ initHabibWalletProvider() {
+ isWalletAmountLoading = true;
+ habibWalletAmount = 0;
+ notifyListeners();
+ }
+
+ Future getPatientBalanceAmount({Function(dynamic)? onSuccess, Function(String)? onError}) async {
+ final result = await habibWalletRepo.getPatientBalanceAmount();
+
+ result.fold(
+ (failure) async => await errorHandlerService.handleError(failure: failure),
+ (apiResponse) {
+ if (apiResponse.messageStatus == 2) {
+ // dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {});
+ } else if (apiResponse.messageStatus == 1) {
+ habibWalletAmount = apiResponse.data!;
+ isWalletAmountLoading = false;
+ notifyListeners();
+ if (onSuccess != null) {
+ onSuccess(apiResponse);
+ }
+ }
+ },
+ );
+ }
+}
diff --git a/lib/features/lab/lab_repo.dart b/lib/features/lab/lab_repo.dart
index ede2ec8..f205494 100644
--- a/lib/features/lab/lab_repo.dart
+++ b/lib/features/lab/lab_repo.dart
@@ -7,7 +7,7 @@ import 'package:hmg_patient_app_new/features/lab/models/resp_models/patient_lab_
import 'package:hmg_patient_app_new/services/logger_service.dart';
abstract class LabRepo {
- Future>>> getPatientLabOrders({required String patientId});
+ Future>>> getPatientLabOrders();
}
class LabRepoImp implements LabRepo {
@@ -17,7 +17,7 @@ class LabRepoImp implements LabRepo {
LabRepoImp({required this.loggerService, required this.apiClient});
@override
- Future>>> getPatientLabOrders({required String patientId}) async {
+ Future>>> getPatientLabOrders() async {
Map mapDevice = {};
try {
diff --git a/lib/features/lab/lab_view_model.dart b/lib/features/lab/lab_view_model.dart
index 52f470d..2e481f4 100644
--- a/lib/features/lab/lab_view_model.dart
+++ b/lib/features/lab/lab_view_model.dart
@@ -29,7 +29,7 @@ class LabViewModel extends ChangeNotifier {
}
Future getPatientLabOrders({Function(dynamic)? onSuccess, Function(String)? onError}) async {
- final result = await labRepo.getPatientLabOrders(patientId: "1231755");
+ final result = await labRepo.getPatientLabOrders();
result.fold(
(failure) async => await errorHandlerService.handleError(failure: failure),
diff --git a/lib/features/medical_file/medical_file_repo.dart b/lib/features/medical_file/medical_file_repo.dart
new file mode 100644
index 0000000..affe564
--- /dev/null
+++ b/lib/features/medical_file/medical_file_repo.dart
@@ -0,0 +1,270 @@
+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/common_models/generic_api_model.dart';
+import 'package:hmg_patient_app_new/core/exceptions/api_failure.dart';
+import 'package:hmg_patient_app_new/core/utils/date_util.dart';
+import 'package:hmg_patient_app_new/core/utils/utils.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/logger_service.dart';
+
+import '../authentication/models/resp_models/authenticated_user_resp_model.dart';
+
+abstract class MedicalFileRepo {
+ Future>>> getPatientVaccinesList();
+
+ Future>>> getPatientSickLeavesList();
+
+ Future>> getPatientSickLeavePDF(PatientSickLeavesResponseModel patientSickLeavesResponseModel, AuthenticatedUser authenticatedUser);
+
+ Future>>> getPatientMedicalReportsList();
+
+ Future>> getPatientMedicalReportPDF(PatientMedicalReportResponseModel patientMedicalReportResponseModel, AuthenticatedUser authenticatedUser);
+}
+
+class MedicalFileRepoImp implements MedicalFileRepo {
+ final ApiClient apiClient;
+ final LoggerService loggerService;
+
+ MedicalFileRepoImp({required this.loggerService, required this.apiClient});
+
+ @override
+ Future>>> getPatientVaccinesList() async {
+ Map mapDevice = {"To": "0", "From": "0"};
+
+ try {
+ GenericApiModel>? apiResponse;
+ Failure? failure;
+ await apiClient.post(
+ GET_VACCINES,
+ body: mapDevice,
+ onFailure: (error, statusCode, {messageStatus, failureType}) {
+ failure = failureType;
+ },
+ onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
+ try {
+ final list = response['List_DoneVaccines'];
+ // if (list == null || list.isEmpty) {
+ // throw Exception("lab list is empty");
+ // }
+
+ final vaccinesList = list.map((item) => PatientVaccineResponseModel.fromJson(item as Map)).toList().cast();
+
+ apiResponse = GenericApiModel>(
+ messageStatus: messageStatus,
+ statusCode: statusCode,
+ errorMessage: null,
+ data: vaccinesList,
+ );
+ } 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>>> getPatientSickLeavesList() async {
+ Map mapDevice = {};
+
+ try {
+ GenericApiModel>? apiResponse;
+ Failure? failure;
+ await apiClient.post(
+ GET_PATIENT_SICK_LEAVE_STATUS,
+ body: mapDevice,
+ onFailure: (error, statusCode, {messageStatus, failureType}) {
+ failure = failureType;
+ },
+ onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
+ try {
+ final list = response['List_SickLeave'];
+ // if (list == null || list.isEmpty) {
+ // throw Exception("lab list is empty");
+ // }
+
+ final vaccinesList = list.map((item) => PatientSickLeavesResponseModel.fromJson(item as Map)).toList().cast();
+
+ apiResponse = GenericApiModel>(
+ messageStatus: messageStatus,
+ statusCode: statusCode,
+ errorMessage: null,
+ data: vaccinesList,
+ );
+ } 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> getPatientSickLeavePDF(PatientSickLeavesResponseModel patientSickLeavesResponseModel, AuthenticatedUser authenticatedUser) async {
+ Map mapDevice = {
+ "RequestNo": patientSickLeavesResponseModel.requestNo,
+ "To": authenticatedUser.emailAddress,
+ "DateofBirth": authenticatedUser.dateofBirth,
+ "PatientIditificationNum": authenticatedUser.patientIdentificationNo,
+ "PatientMobileNumber": authenticatedUser.mobileNumber,
+ "PatientName": "${authenticatedUser.firstName!} ${authenticatedUser.lastName!}",
+ "ProjectName": patientSickLeavesResponseModel.projectName,
+ "DoctorName": patientSickLeavesResponseModel.doctorName,
+ "ProjectID": patientSickLeavesResponseModel.projectID,
+ "SetupID": patientSickLeavesResponseModel.setupID,
+ "IsDownload": true,
+ };
+
+ try {
+ GenericApiModel? apiResponse;
+ Failure? failure;
+ await apiClient.post(
+ SendSickLeaveEmail,
+ body: mapDevice,
+ onFailure: (error, statusCode, {messageStatus, failureType}) {
+ failure = failureType;
+ },
+ onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
+ try {
+ // final list = response['List_SickLeave'];
+ // if (list == null || list.isEmpty) {
+ // throw Exception("lab list is empty");
+ // }
+
+ // final vaccinesList = list.map((item) => PatientSickLeavesResponseModel.fromJson(item as Map)).toList().cast();
+
+ apiResponse = GenericApiModel(
+ messageStatus: messageStatus,
+ statusCode: statusCode,
+ errorMessage: null,
+ data: response["Base64Data"],
+ );
+ } 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>>> getPatientMedicalReportsList() async {
+ Map mapDevice = {
+ "IsReport": true,
+ "EncounterType": 1,
+ "RequestType": 1,
+ };
+
+ try {
+ GenericApiModel>? apiResponse;
+ Failure? failure;
+ await apiClient.post(
+ REPORTS,
+ body: mapDevice,
+ onFailure: (error, statusCode, {messageStatus, failureType}) {
+ failure = failureType;
+ },
+ onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
+ try {
+ final list = response['GetPatientMedicalStatus'];
+ // if (list == null || list.isEmpty) {
+ // throw Exception("lab list is empty");
+ // }
+
+ final vaccinesList = list.map((item) => PatientMedicalReportResponseModel.fromJson(item as Map)).toList().cast();
+
+ apiResponse = GenericApiModel>(
+ messageStatus: messageStatus,
+ statusCode: statusCode,
+ errorMessage: null,
+ data: vaccinesList,
+ );
+ } 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> getPatientMedicalReportPDF(PatientMedicalReportResponseModel patientMedicalReportResponseModel, AuthenticatedUser authenticatedUser) async {
+ Map mapDevice = {
+ "SetupID": patientMedicalReportResponseModel.setupId,
+ "PrintDate": patientMedicalReportResponseModel.requestDate!,
+ "ProcedureID": "05005009",
+ "Reporttype": "MEDICAL REPORT",
+ "stamp": patientMedicalReportResponseModel.requestDate!,
+ "To": authenticatedUser.emailAddress,
+ "DateofBirth": authenticatedUser.dateofBirth,
+ "PatientIditificationNum": authenticatedUser.patientIdentificationNo,
+ "PatientMobileNumber": authenticatedUser.mobileNumber,
+ "PatientName": "${authenticatedUser.firstName!} ${authenticatedUser.lastName!}",
+ "ProjectName": patientMedicalReportResponseModel.projectName,
+ "ClinicName": patientMedicalReportResponseModel.clinicDescription,
+ "ProjectID": patientMedicalReportResponseModel.projectID,
+ "InvoiceNo": Utils.isVidaPlusProject(patientMedicalReportResponseModel.projectID!) ? patientMedicalReportResponseModel.invoiceNoVP : patientMedicalReportResponseModel.invoiceNo,
+ "InvoiceNo_VP": Utils.isVidaPlusProject(patientMedicalReportResponseModel.projectID!) ? patientMedicalReportResponseModel.invoiceNoVP : patientMedicalReportResponseModel.invoiceNo,
+ "PrintedByName": "${authenticatedUser.firstName!} ${authenticatedUser.lastName!}",
+ };
+
+ try {
+ GenericApiModel? apiResponse;
+ Failure? failure;
+ await apiClient.post(
+ GET_MEDICAL_REPORT_PDF,
+ body: mapDevice,
+ onFailure: (error, statusCode, {messageStatus, failureType}) {
+ failure = failureType;
+ },
+ onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
+ try {
+ // final list = response['List_SickLeave'];
+ // if (list == null || list.isEmpty) {
+ // throw Exception("lab list is empty");
+ // }
+
+ // final vaccinesList = list.map((item) => PatientSickLeavesResponseModel.fromJson(item as Map)).toList().cast();
+
+ apiResponse = GenericApiModel(
+ messageStatus: messageStatus,
+ statusCode: statusCode,
+ errorMessage: null,
+ data: response["MedicalReportBase64"],
+ );
+ } 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 8c00fe4..73167bb 100644
--- a/lib/features/medical_file/medical_file_view_model.dart
+++ b/lib/features/medical_file/medical_file_view_model.dart
@@ -1,12 +1,220 @@
import 'package:flutter/material.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/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/error_handler_service.dart';
class MedicalFileViewModel extends ChangeNotifier {
-
int selectedTabIndex = 0;
+ bool isPatientVaccineListLoading = false;
+ bool isPatientSickLeaveListLoading = false;
+ bool isPatientSickLeavePDFLoading = false;
+ bool isPatientMedicalReportsListLoading = false;
+
+ MedicalFileRepo medicalFileRepo;
+ ErrorHandlerService errorHandlerService;
+
+ List patientVaccineList = [];
+ List patientSickLeaveList = [];
+
+ List patientMedicalReportList = [];
+
+ List patientMedicalReportRequestedList = [];
+ List patientMedicalReportReadyList = [];
+ List patientMedicalReportCancelledList = [];
+
+ String patientSickLeavePDFBase64 = "";
+ String patientMedicalReportPDFBase64 = "";
+
+ int selectedMedicalReportsTabIndex = 0;
+
+ MedicalFileViewModel({required this.medicalFileRepo, required this.errorHandlerService});
+
+ initMedicalFileProvider() {
+ isPatientVaccineListLoading = true;
+ isPatientMedicalReportsListLoading = true;
+ notifyListeners();
+ }
+
+ void onMedicalReportTabChange(int index) {
+ selectedMedicalReportsTabIndex = index;
+ if (index == 0) {
+ patientMedicalReportList = patientMedicalReportRequestedList;
+ } else if (index == 1) {
+ patientMedicalReportList = patientMedicalReportReadyList;
+ } else if (index == 2) {
+ patientMedicalReportList = patientMedicalReportCancelledList;
+ }
+ notifyListeners();
+ }
+
+ setIsPatientVaccineListLoading(bool isLoading) {
+ isPatientVaccineListLoading = isLoading;
+ notifyListeners();
+ }
+
+ setIsPatientSickLeavePDFLoading(bool isLoading) {
+ isPatientSickLeavePDFLoading = isLoading;
+ notifyListeners();
+ }
+
+ setIsPatientSickLeaveListLoading(bool val) {
+ if (val) {
+ patientSickLeaveList.clear();
+ patientSickLeavePDFBase64 = "";
+ }
+ isPatientSickLeaveListLoading = val;
+ notifyListeners();
+ }
+
+ setIsPatientMedicalReportsLoading(bool val) {
+ if (val) {
+ patientMedicalReportList.clear();
+ patientMedicalReportPDFBase64 = "";
+ }
+ isPatientMedicalReportsListLoading = val;
+ notifyListeners();
+ }
void onTabChanged(int index) {
selectedTabIndex = index;
notifyListeners();
}
+ Future getPatientVaccinesList({Function(dynamic)? onSuccess, Function(String)? onError}) async {
+ patientVaccineList.clear();
+ final result = await medicalFileRepo.getPatientVaccinesList();
+
+ result.fold(
+ (failure) async => await errorHandlerService.handleError(
+ failure: failure,
+ onOkPressed: () {
+ onError!(failure.message);
+ },
+ ),
+ (apiResponse) {
+ if (apiResponse.messageStatus == 2) {
+ // dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {});
+ } else if (apiResponse.messageStatus == 1) {
+ patientVaccineList = apiResponse.data!;
+ isPatientVaccineListLoading = false;
+ notifyListeners();
+ if (onSuccess != null) {
+ onSuccess(apiResponse);
+ }
+ }
+ },
+ );
+ }
+
+ Future getPatientSickLeaveList({Function(dynamic)? onSuccess, Function(String)? onError}) async {
+ patientSickLeaveList.clear();
+ final result = await medicalFileRepo.getPatientSickLeavesList();
+
+ result.fold(
+ (failure) async => await errorHandlerService.handleError(
+ failure: failure,
+ onOkPressed: () {
+ onError!(failure.message);
+ },
+ ),
+ (apiResponse) {
+ if (apiResponse.messageStatus == 2) {
+ // dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {});
+ } else if (apiResponse.messageStatus == 1) {
+ patientSickLeaveList = apiResponse.data!;
+ isPatientSickLeaveListLoading = false;
+ notifyListeners();
+ if (onSuccess != null) {
+ onSuccess(apiResponse);
+ }
+ }
+ },
+ );
+ }
+
+ Future getPatientSickLeavePDF(PatientSickLeavesResponseModel patientSickLeavesResponseModel, AuthenticatedUser authenticatedUser,
+ {Function(dynamic)? onSuccess, Function(String)? onError}) async {
+ final result = await medicalFileRepo.getPatientSickLeavePDF(patientSickLeavesResponseModel, authenticatedUser);
+
+ result.fold(
+ (failure) async => await errorHandlerService.handleError(
+ failure: failure,
+ onOkPressed: () {
+ onError!(failure.message);
+ },
+ ),
+ (apiResponse) {
+ if (apiResponse.messageStatus == 2) {
+ // dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {});
+ } else if (apiResponse.messageStatus == 1) {
+ patientSickLeavePDFBase64 = apiResponse.data!;
+ isPatientSickLeaveListLoading = false;
+ notifyListeners();
+ if (onSuccess != null) {
+ onSuccess(apiResponse);
+ }
+ }
+ },
+ );
+ }
+
+ Future getPatientMedicalReportList({Function(dynamic)? onSuccess, Function(String)? onError}) async {
+ patientMedicalReportList.clear();
+ final result = await medicalFileRepo.getPatientMedicalReportsList();
+
+ result.fold(
+ (failure) async => await errorHandlerService.handleError(
+ failure: failure,
+ onOkPressed: () {
+ onError!(failure.message);
+ },
+ ),
+ (apiResponse) {
+ if (apiResponse.messageStatus == 2) {
+ // dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {});
+ } else if (apiResponse.messageStatus == 1) {
+ patientMedicalReportList = apiResponse.data!;
+ if (patientMedicalReportList.isNotEmpty) {
+ patientMedicalReportRequestedList = patientMedicalReportList.where((element) => element.status == 1).toList();
+ patientMedicalReportReadyList = patientMedicalReportList.where((element) => element.status == 2).toList();
+ patientMedicalReportCancelledList = patientMedicalReportList.where((element) => element.status == 4).toList();
+ }
+ onMedicalReportTabChange(0);
+ isPatientMedicalReportsListLoading = false;
+ notifyListeners();
+ if (onSuccess != null) {
+ onSuccess(apiResponse);
+ }
+ }
+ },
+ );
+ }
+
+ Future getPatientMedicalReportPDF(PatientMedicalReportResponseModel patientMedicalReportResponseModel, AuthenticatedUser authenticatedUser,
+ {Function(dynamic)? onSuccess, Function(String)? onError}) async {
+ final result = await medicalFileRepo.getPatientMedicalReportPDF(patientMedicalReportResponseModel, authenticatedUser);
+
+ result.fold(
+ (failure) async => await errorHandlerService.handleError(
+ failure: failure,
+ onOkPressed: () {
+ onError!(failure.message);
+ },
+ ),
+ (apiResponse) {
+ if (apiResponse.messageStatus == 2) {
+ // dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {});
+ } else if (apiResponse.messageStatus == 1) {
+ patientMedicalReportPDFBase64 = apiResponse.data!;
+ notifyListeners();
+ if (onSuccess != null) {
+ onSuccess(apiResponse);
+ }
+ }
+ },
+ );
+ }
}
diff --git a/lib/features/medical_file/models/patient_medical_response_model.dart b/lib/features/medical_file/models/patient_medical_response_model.dart
new file mode 100644
index 0000000..52785af
--- /dev/null
+++ b/lib/features/medical_file/models/patient_medical_response_model.dart
@@ -0,0 +1,192 @@
+class PatientMedicalReportResponseModel {
+ int? status;
+ String? encounterDate;
+ int? projectID;
+ int? invoiceNo;
+ int? encounterNo;
+ String? procedureId;
+ int? requestType;
+ String? setupId;
+ int? patientID;
+ int? doctorID;
+ int? clinicID;
+ String? requestDate;
+ bool? isRead;
+ dynamic isReadOn;
+ num? actualDoctorRate;
+ String? admissionDate;
+ int? admissionNumber;
+ String? appointmentDate;
+ int? appointmentNO;
+ String? appointmentTime;
+ String? clinicDescription;
+ dynamic clinicDescriptionN;
+ num? decimalDoctorRate;
+ String? docName;
+ dynamic docNameN;
+ String? doctorImageURL;
+ String? doctorName;
+ dynamic doctorNameN;
+ num? doctorRate;
+ num? doctorStarsRate;
+ int? invoiceNoVP;
+ dynamic invoiceType;
+ bool? isDoctorAllowVedioCall;
+ bool? isExecludeDoctor;
+ bool? isInOutPatient;
+ String? isInOutPatientDescription;
+ String? isInOutPatientDescriptionN;
+ int? noOfPatientsRate;
+ String? projectName;
+ dynamic projectNameN;
+ int? sourceID;
+ dynamic sourceName;
+ dynamic sourceNameN;
+ String? statusDesc;
+ dynamic strAppointmentDate;
+
+ PatientMedicalReportResponseModel(
+ {this.status,
+ this.encounterDate,
+ this.projectID,
+ this.invoiceNo,
+ this.encounterNo,
+ this.procedureId,
+ this.requestType,
+ this.setupId,
+ this.patientID,
+ this.doctorID,
+ this.clinicID,
+ this.requestDate,
+ this.isRead,
+ this.isReadOn,
+ this.actualDoctorRate,
+ this.admissionDate,
+ this.admissionNumber,
+ this.appointmentDate,
+ this.appointmentNO,
+ this.appointmentTime,
+ this.clinicDescription,
+ this.clinicDescriptionN,
+ this.decimalDoctorRate,
+ this.docName,
+ this.docNameN,
+ this.doctorImageURL,
+ this.doctorName,
+ this.doctorNameN,
+ this.doctorRate,
+ this.doctorStarsRate,
+ this.invoiceNoVP,
+ this.invoiceType,
+ this.isDoctorAllowVedioCall,
+ this.isExecludeDoctor,
+ this.isInOutPatient,
+ this.isInOutPatientDescription,
+ this.isInOutPatientDescriptionN,
+ this.noOfPatientsRate,
+ this.projectName,
+ this.projectNameN,
+ this.sourceID,
+ this.sourceName,
+ this.sourceNameN,
+ this.statusDesc,
+ this.strAppointmentDate});
+
+ PatientMedicalReportResponseModel.fromJson(Map json) {
+ status = json['Status'];
+ encounterDate = json['EncounterDate'];
+ projectID = json['ProjectID'];
+ invoiceNo = json['InvoiceNo'];
+ encounterNo = json['EncounterNo'];
+ procedureId = json['ProcedureId'];
+ requestType = json['RequestType'];
+ setupId = json['SetupId'];
+ patientID = json['PatientID'];
+ doctorID = json['DoctorID'];
+ clinicID = json['ClinicID'];
+ requestDate = json['RequestDate'];
+ isRead = json['IsRead'];
+ isReadOn = json['IsReadOn'];
+ actualDoctorRate = json['ActualDoctorRate'];
+ admissionDate = json['AdmissionDate'];
+ admissionNumber = json['AdmissionNumber'];
+ appointmentDate = json['AppointmentDate'];
+ appointmentNO = json['AppointmentNO'];
+ appointmentTime = json['AppointmentTime'];
+ clinicDescription = json['ClinicDescription'];
+ clinicDescriptionN = json['ClinicDescriptionN'];
+ decimalDoctorRate = json['DecimalDoctorRate'];
+ docName = json['DocName'];
+ docNameN = json['DocNameN'];
+ doctorImageURL = json['DoctorImageURL'];
+ doctorName = json['DoctorName'];
+ doctorNameN = json['DoctorNameN'];
+ doctorRate = json['DoctorRate'];
+ doctorStarsRate = json['DoctorStarsRate'];
+ invoiceNoVP = json['InvoiceNo_VP'];
+ invoiceType = json['InvoiceType'];
+ isDoctorAllowVedioCall = json['IsDoctorAllowVedioCall'];
+ isExecludeDoctor = json['IsExecludeDoctor'];
+ isInOutPatient = json['IsInOutPatient'];
+ isInOutPatientDescription = json['IsInOutPatientDescription'];
+ isInOutPatientDescriptionN = json['IsInOutPatientDescriptionN'];
+ noOfPatientsRate = json['NoOfPatientsRate'];
+ projectName = json['ProjectName'];
+ projectNameN = json['ProjectNameN'];
+ sourceID = json['SourceID'];
+ sourceName = json['SourceName'];
+ sourceNameN = json['SourceNameN'];
+ statusDesc = json['StatusDesc'];
+ strAppointmentDate = json['StrAppointmentDate'];
+ }
+
+ Map toJson() {
+ final Map data = new Map();
+ data['Status'] = this.status;
+ data['EncounterDate'] = this.encounterDate;
+ data['ProjectID'] = this.projectID;
+ data['InvoiceNo'] = this.invoiceNo;
+ data['EncounterNo'] = this.encounterNo;
+ data['ProcedureId'] = this.procedureId;
+ data['RequestType'] = this.requestType;
+ data['SetupId'] = this.setupId;
+ data['PatientID'] = this.patientID;
+ data['DoctorID'] = this.doctorID;
+ data['ClinicID'] = this.clinicID;
+ data['RequestDate'] = this.requestDate;
+ data['IsRead'] = this.isRead;
+ data['IsReadOn'] = this.isReadOn;
+ data['ActualDoctorRate'] = this.actualDoctorRate;
+ data['AdmissionDate'] = this.admissionDate;
+ data['AdmissionNumber'] = this.admissionNumber;
+ data['AppointmentDate'] = this.appointmentDate;
+ data['AppointmentNO'] = this.appointmentNO;
+ data['AppointmentTime'] = this.appointmentTime;
+ data['ClinicDescription'] = this.clinicDescription;
+ data['ClinicDescriptionN'] = this.clinicDescriptionN;
+ data['DecimalDoctorRate'] = this.decimalDoctorRate;
+ data['DocName'] = this.docName;
+ data['DocNameN'] = this.docNameN;
+ data['DoctorImageURL'] = this.doctorImageURL;
+ data['DoctorName'] = this.doctorName;
+ data['DoctorNameN'] = this.doctorNameN;
+ data['DoctorRate'] = this.doctorRate;
+ data['DoctorStarsRate'] = this.doctorStarsRate;
+ data['InvoiceNo_VP'] = this.invoiceNoVP;
+ data['InvoiceType'] = this.invoiceType;
+ data['IsDoctorAllowVedioCall'] = this.isDoctorAllowVedioCall;
+ data['IsExecludeDoctor'] = this.isExecludeDoctor;
+ data['IsInOutPatient'] = this.isInOutPatient;
+ data['IsInOutPatientDescription'] = this.isInOutPatientDescription;
+ data['IsInOutPatientDescriptionN'] = this.isInOutPatientDescriptionN;
+ data['NoOfPatientsRate'] = this.noOfPatientsRate;
+ data['ProjectName'] = this.projectName;
+ data['ProjectNameN'] = this.projectNameN;
+ data['SourceID'] = this.sourceID;
+ data['SourceName'] = this.sourceName;
+ data['SourceNameN'] = this.sourceNameN;
+ data['StatusDesc'] = this.statusDesc;
+ data['StrAppointmentDate'] = this.strAppointmentDate;
+ return data;
+ }
+}
diff --git a/lib/features/medical_file/models/patient_sickleave_response_model.dart b/lib/features/medical_file/models/patient_sickleave_response_model.dart
new file mode 100644
index 0000000..b0381a8
--- /dev/null
+++ b/lib/features/medical_file/models/patient_sickleave_response_model.dart
@@ -0,0 +1,176 @@
+class PatientSickLeavesResponseModel {
+ String? setupID;
+ int? projectID;
+ int? patientID;
+ int? patientType;
+ int? clinicID;
+ int? doctorID;
+ int? requestNo;
+ String? requestDate;
+ int? sickLeaveDays;
+ int? appointmentNo;
+ int? admissionNo;
+ dynamic reportDate;
+ num? actualDoctorRate;
+ String? appointmentDate;
+ String? clinicName;
+ double? decimalDoctorRate;
+ String? doctorImageURL;
+ String? doctorName;
+ num? doctorRate;
+ num? doctorStarsRate;
+ String? doctorTitle;
+ int? employeeID;
+ String? endDate;
+ int? gender;
+ String? genderDescription;
+ bool? isActiveDoctorProfile;
+ bool? isDoctorAllowVedioCall;
+ bool? isExecludeDoctor;
+ bool? isInOutPatient;
+ String? isInOutPatientDescription;
+ String? isInOutPatientDescriptionN;
+ bool? isLiveCareAppointment;
+ dynamic medicalDirectorApprovedStatus;
+ int? noOfPatientsRate;
+ dynamic patientName;
+ String? projectName;
+ String? qR;
+ List? speciality;
+ String? startDate;
+ int? status;
+ String? strRequestDate;
+
+ PatientSickLeavesResponseModel(
+ {this.setupID,
+ this.projectID,
+ this.patientID,
+ this.patientType,
+ this.clinicID,
+ this.doctorID,
+ this.requestNo,
+ this.requestDate,
+ this.sickLeaveDays,
+ this.appointmentNo,
+ this.admissionNo,
+ this.reportDate,
+ this.actualDoctorRate,
+ this.appointmentDate,
+ this.clinicName,
+ this.decimalDoctorRate,
+ this.doctorImageURL,
+ this.doctorName,
+ this.doctorRate,
+ this.doctorStarsRate,
+ this.doctorTitle,
+ this.employeeID,
+ this.endDate,
+ this.gender,
+ this.genderDescription,
+ this.isActiveDoctorProfile,
+ this.isDoctorAllowVedioCall,
+ this.isExecludeDoctor,
+ this.isInOutPatient,
+ this.isInOutPatientDescription,
+ this.isInOutPatientDescriptionN,
+ this.isLiveCareAppointment,
+ this.medicalDirectorApprovedStatus,
+ this.noOfPatientsRate,
+ this.patientName,
+ this.projectName,
+ this.qR,
+ this.speciality,
+ this.startDate,
+ this.status,
+ this.strRequestDate});
+
+ PatientSickLeavesResponseModel.fromJson(Map json) {
+ setupID = json['SetupID'];
+ projectID = json['ProjectID'];
+ patientID = json['PatientID'];
+ patientType = json['PatientType'];
+ clinicID = json['ClinicID'];
+ doctorID = json['DoctorID'];
+ requestNo = json['RequestNo'];
+ requestDate = json['RequestDate'];
+ sickLeaveDays = json['SickLeaveDays'];
+ appointmentNo = json['AppointmentNo'];
+ admissionNo = json['AdmissionNo'];
+ reportDate = json['ReportDate'];
+ actualDoctorRate = json['ActualDoctorRate'];
+ appointmentDate = json['AppointmentDate'];
+ clinicName = json['ClinicName'];
+ decimalDoctorRate = json['DecimalDoctorRate'];
+ doctorImageURL = json['DoctorImageURL'];
+ doctorName = json['DoctorName'];
+ doctorRate = json['DoctorRate'];
+ doctorStarsRate = json['DoctorStarsRate'];
+ doctorTitle = json['DoctorTitle'];
+ employeeID = json['EmployeeID'];
+ endDate = json['EndDate'];
+ gender = json['Gender'];
+ genderDescription = json['GenderDescription'];
+ isActiveDoctorProfile = json['IsActiveDoctorProfile'];
+ isDoctorAllowVedioCall = json['IsDoctorAllowVedioCall'];
+ isExecludeDoctor = json['IsExecludeDoctor'];
+ isInOutPatient = json['IsInOutPatient'];
+ isInOutPatientDescription = json['IsInOutPatientDescription'];
+ isInOutPatientDescriptionN = json['IsInOutPatientDescriptionN'];
+ isLiveCareAppointment = json['IsLiveCareAppointment'];
+ medicalDirectorApprovedStatus = json['MedicalDirectorApprovedStatus'];
+ noOfPatientsRate = json['NoOfPatientsRate'];
+ patientName = json['PatientName'];
+ projectName = json['ProjectName'];
+ qR = json['QR'];
+ speciality = json['Speciality'].cast();
+ startDate = json['StartDate'];
+ status = json['Status'];
+ strRequestDate = json['StrRequestDate'];
+ }
+
+ Map toJson() {
+ final Map data = new Map();
+ data['SetupID'] = this.setupID;
+ data['ProjectID'] = this.projectID;
+ data['PatientID'] = this.patientID;
+ data['PatientType'] = this.patientType;
+ data['ClinicID'] = this.clinicID;
+ data['DoctorID'] = this.doctorID;
+ data['RequestNo'] = this.requestNo;
+ data['RequestDate'] = this.requestDate;
+ data['SickLeaveDays'] = this.sickLeaveDays;
+ data['AppointmentNo'] = this.appointmentNo;
+ data['AdmissionNo'] = this.admissionNo;
+ data['ReportDate'] = this.reportDate;
+ data['ActualDoctorRate'] = this.actualDoctorRate;
+ data['AppointmentDate'] = this.appointmentDate;
+ data['ClinicName'] = this.clinicName;
+ data['DecimalDoctorRate'] = this.decimalDoctorRate;
+ data['DoctorImageURL'] = this.doctorImageURL;
+ data['DoctorName'] = this.doctorName;
+ data['DoctorRate'] = this.doctorRate;
+ data['DoctorStarsRate'] = this.doctorStarsRate;
+ data['DoctorTitle'] = this.doctorTitle;
+ data['EmployeeID'] = this.employeeID;
+ data['EndDate'] = this.endDate;
+ data['Gender'] = this.gender;
+ data['GenderDescription'] = this.genderDescription;
+ data['IsActiveDoctorProfile'] = this.isActiveDoctorProfile;
+ data['IsDoctorAllowVedioCall'] = this.isDoctorAllowVedioCall;
+ data['IsExecludeDoctor'] = this.isExecludeDoctor;
+ data['IsInOutPatient'] = this.isInOutPatient;
+ data['IsInOutPatientDescription'] = this.isInOutPatientDescription;
+ data['IsInOutPatientDescriptionN'] = this.isInOutPatientDescriptionN;
+ data['IsLiveCareAppointment'] = this.isLiveCareAppointment;
+ data['MedicalDirectorApprovedStatus'] = this.medicalDirectorApprovedStatus;
+ data['NoOfPatientsRate'] = this.noOfPatientsRate;
+ data['PatientName'] = this.patientName;
+ data['ProjectName'] = this.projectName;
+ data['QR'] = this.qR;
+ data['Speciality'] = this.speciality;
+ data['StartDate'] = this.startDate;
+ data['Status'] = this.status;
+ data['StrRequestDate'] = this.strRequestDate;
+ return data;
+ }
+}
diff --git a/lib/features/medical_file/models/patient_vaccine_response_model.dart b/lib/features/medical_file/models/patient_vaccine_response_model.dart
new file mode 100644
index 0000000..ff27b06
--- /dev/null
+++ b/lib/features/medical_file/models/patient_vaccine_response_model.dart
@@ -0,0 +1,160 @@
+class PatientVaccineResponseModel {
+ String? setupID;
+ int? projectID;
+ int? patientID;
+ int? invoiceNo;
+ String? procedureID;
+ String? vaccineName;
+ Null? vaccineNameN;
+ String? invoiceDate;
+ int? doctorID;
+ int? clinicID;
+ String? firstName;
+ String? middleName;
+ String? lastName;
+ Null? firstNameN;
+ Null? middleNameN;
+ Null? lastNameN;
+ String? dateofBirth;
+ int? actualDoctorRate;
+ String? age;
+ String? clinicName;
+ Null? decimalDoctorRate;
+ Null? doctorImageURL;
+ String? doctorName;
+ int? doctorRate;
+ int? doctorStarsRate;
+ String? doctorTitle;
+ int? gender;
+ Null? genderDescription;
+ Null? invoiceNoVP;
+ bool? isActiveDoctorProfile;
+ bool? isDoctorAllowVedioCall;
+ bool? isExecludeDoctor;
+ int? noOfPatientsRate;
+ String? patientName;
+ String? projectName;
+ String? qR;
+ String? vaccinationDate;
+
+ PatientVaccineResponseModel(
+ {this.setupID,
+ this.projectID,
+ this.patientID,
+ this.invoiceNo,
+ this.procedureID,
+ this.vaccineName,
+ this.vaccineNameN,
+ this.invoiceDate,
+ this.doctorID,
+ this.clinicID,
+ this.firstName,
+ this.middleName,
+ this.lastName,
+ this.firstNameN,
+ this.middleNameN,
+ this.lastNameN,
+ this.dateofBirth,
+ this.actualDoctorRate,
+ this.age,
+ this.clinicName,
+ this.decimalDoctorRate,
+ this.doctorImageURL,
+ this.doctorName,
+ this.doctorRate,
+ this.doctorStarsRate,
+ this.doctorTitle,
+ this.gender,
+ this.genderDescription,
+ this.invoiceNoVP,
+ this.isActiveDoctorProfile,
+ this.isDoctorAllowVedioCall,
+ this.isExecludeDoctor,
+ this.noOfPatientsRate,
+ this.patientName,
+ this.projectName,
+ this.qR,
+ this.vaccinationDate});
+
+ PatientVaccineResponseModel.fromJson(Map json) {
+ setupID = json['SetupID'];
+ projectID = json['ProjectID'];
+ patientID = json['PatientID'];
+ invoiceNo = json['InvoiceNo'];
+ procedureID = json['ProcedureID'];
+ vaccineName = json['VaccineName'];
+ vaccineNameN = json['VaccineNameN'];
+ invoiceDate = json['InvoiceDate'];
+ doctorID = json['DoctorID'];
+ clinicID = json['ClinicID'];
+ firstName = json['FirstName'];
+ middleName = json['MiddleName'];
+ lastName = json['LastName'];
+ firstNameN = json['FirstNameN'];
+ middleNameN = json['MiddleNameN'];
+ lastNameN = json['LastNameN'];
+ dateofBirth = json['DateofBirth'];
+ actualDoctorRate = json['ActualDoctorRate'];
+ age = json['Age'];
+ clinicName = json['ClinicName'];
+ decimalDoctorRate = json['DecimalDoctorRate'];
+ doctorImageURL = json['DoctorImageURL'];
+ doctorName = json['DoctorName'];
+ doctorRate = json['DoctorRate'];
+ doctorStarsRate = json['DoctorStarsRate'];
+ doctorTitle = json['DoctorTitle'];
+ gender = json['Gender'];
+ genderDescription = json['GenderDescription'];
+ invoiceNoVP = json['InvoiceNo_VP'];
+ isActiveDoctorProfile = json['IsActiveDoctorProfile'];
+ isDoctorAllowVedioCall = json['IsDoctorAllowVedioCall'];
+ isExecludeDoctor = json['IsExecludeDoctor'];
+ noOfPatientsRate = json['NoOfPatientsRate'];
+ patientName = json['PatientName'];
+ projectName = json['ProjectName'];
+ qR = json['QR'];
+ vaccinationDate = json['VaccinationDate'];
+ }
+
+ Map toJson() {
+ final Map data = new Map();
+ data['SetupID'] = this.setupID;
+ data['ProjectID'] = this.projectID;
+ data['PatientID'] = this.patientID;
+ data['InvoiceNo'] = this.invoiceNo;
+ data['ProcedureID'] = this.procedureID;
+ data['VaccineName'] = this.vaccineName;
+ data['VaccineNameN'] = this.vaccineNameN;
+ data['InvoiceDate'] = this.invoiceDate;
+ data['DoctorID'] = this.doctorID;
+ data['ClinicID'] = this.clinicID;
+ data['FirstName'] = this.firstName;
+ data['MiddleName'] = this.middleName;
+ data['LastName'] = this.lastName;
+ data['FirstNameN'] = this.firstNameN;
+ data['MiddleNameN'] = this.middleNameN;
+ data['LastNameN'] = this.lastNameN;
+ data['DateofBirth'] = this.dateofBirth;
+ data['ActualDoctorRate'] = this.actualDoctorRate;
+ data['Age'] = this.age;
+ data['ClinicName'] = this.clinicName;
+ data['DecimalDoctorRate'] = this.decimalDoctorRate;
+ data['DoctorImageURL'] = this.doctorImageURL;
+ data['DoctorName'] = this.doctorName;
+ data['DoctorRate'] = this.doctorRate;
+ data['DoctorStarsRate'] = this.doctorStarsRate;
+ data['DoctorTitle'] = this.doctorTitle;
+ data['Gender'] = this.gender;
+ data['GenderDescription'] = this.genderDescription;
+ data['InvoiceNo_VP'] = this.invoiceNoVP;
+ data['IsActiveDoctorProfile'] = this.isActiveDoctorProfile;
+ data['IsDoctorAllowVedioCall'] = this.isDoctorAllowVedioCall;
+ data['IsExecludeDoctor'] = this.isExecludeDoctor;
+ data['NoOfPatientsRate'] = this.noOfPatientsRate;
+ data['PatientName'] = this.patientName;
+ data['ProjectName'] = this.projectName;
+ data['QR'] = this.qR;
+ data['VaccinationDate'] = this.vaccinationDate;
+ return data;
+ }
+}
diff --git a/lib/features/my_appointments/my_appointments_repo.dart b/lib/features/my_appointments/my_appointments_repo.dart
index 804f9f9..2035f30 100644
--- a/lib/features/my_appointments/my_appointments_repo.dart
+++ b/lib/features/my_appointments/my_appointments_repo.dart
@@ -32,6 +32,10 @@ abstract class MyAppointmentsRepo {
Future>> sendCheckInNfcRequest(
{required PatientAppointmentHistoryResponseModel patientAppointmentHistoryResponseModel, required String scannedCode, required int checkInType});
+
+ Future>>> getPatientAppointmentsForTimeLine();
+
+ Future>>> getPatientDoctorsList();
}
class MyAppointmentsRepoImp implements MyAppointmentsRepo {
@@ -395,4 +399,96 @@ class MyAppointmentsRepoImp implements MyAppointmentsRepo {
return Left(UnknownFailure(e.toString()));
}
}
+
+ @override
+ Future>>> getPatientAppointmentsForTimeLine() async {
+ Map mapDevice = {
+ "isDentalAllowedBackend": false,
+ "PatientTypeID": 1,
+ "IsComingFromCOC": false,
+ "PatientType": 1,
+ "IsForTimeLine": true,
+ };
+
+ try {
+ GenericApiModel>? apiResponse;
+ Failure? failure;
+ await apiClient.post(
+ GET_PATIENT_APPOINTMENT_HISTORY,
+ body: mapDevice,
+ onFailure: (error, statusCode, {messageStatus, failureType}) {
+ failure = failureType;
+ },
+ onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
+ try {
+ final list = response['AppoimentAllHistoryResultList'];
+ // if (list == null || list.isEmpty) {
+ // throw Exception("Appointments list is empty");
+ // }
+
+ final appointmentsList = list.map((item) => PatientAppointmentHistoryResponseModel.fromJson(item as Map)).toList().cast();
+
+ apiResponse = GenericApiModel>(
+ messageStatus: messageStatus,
+ statusCode: statusCode,
+ errorMessage: null,
+ data: appointmentsList,
+ );
+ } 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>>> getPatientDoctorsList() async {
+ Map mapDevice = {
+ "Top": 0,
+ "beforeDays": 0,
+ "exludType": 4,
+ };
+
+ try {
+ GenericApiModel>? apiResponse;
+ Failure? failure;
+ await apiClient.post(
+ GET_MY_DOCTOR,
+ body: mapDevice,
+ onFailure: (error, statusCode, {messageStatus, failureType}) {
+ failure = failureType;
+ },
+ onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
+ try {
+ final list = response['PatientDoctorAppointmentResultList'];
+ // if (list == null || list.isEmpty) {
+ // throw Exception("Appointments list is empty");
+ // }
+
+ final appointmentsList = list.map((item) => PatientAppointmentHistoryResponseModel.fromJson(item as Map)).toList().cast();
+
+ apiResponse = GenericApiModel>(
+ messageStatus: messageStatus,
+ statusCode: statusCode,
+ errorMessage: null,
+ data: appointmentsList,
+ );
+ } 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/my_appointments/my_appointments_view_model.dart b/lib/features/my_appointments/my_appointments_view_model.dart
index 4a921da..c6d3499 100644
--- a/lib/features/my_appointments/my_appointments_view_model.dart
+++ b/lib/features/my_appointments/my_appointments_view_model.dart
@@ -12,12 +12,18 @@ class MyAppointmentsViewModel extends ChangeNotifier {
bool isMyAppointmentsLoading = false;
bool isAppointmentPatientShareLoading = false;
+ bool isTimeLineAppointmentsLoading = false;
+ bool isPatientMyDoctorsLoading = false;
List patientAppointmentsHistoryList = [];
List patientUpcomingAppointmentsHistoryList = [];
List patientArrivedAppointmentsHistoryList = [];
+ List patientTimelineAppointmentsList = [];
+
+ List patientMyDoctorsList = [];
+
PatientAppointmentShareResponseModel? patientAppointmentShareResponseModel;
MyAppointmentsViewModel({required this.myAppointmentsRepo, required this.errorHandlerService});
@@ -31,8 +37,12 @@ class MyAppointmentsViewModel extends ChangeNotifier {
patientAppointmentsHistoryList.clear();
patientUpcomingAppointmentsHistoryList.clear();
patientArrivedAppointmentsHistoryList.clear();
+ patientTimelineAppointmentsList.clear();
+ patientMyDoctorsList.clear();
isMyAppointmentsLoading = true;
isAppointmentPatientShareLoading = true;
+ isTimeLineAppointmentsLoading = true;
+ isPatientMyDoctorsLoading = true;
notifyListeners();
}
@@ -46,6 +56,16 @@ class MyAppointmentsViewModel extends ChangeNotifier {
notifyListeners();
}
+ setIsPatientTimeLineAppointmentLoading(bool val) {
+ isTimeLineAppointmentsLoading = val;
+ notifyListeners();
+ }
+
+ setIsPatientMyDoctorsLoading(bool val) {
+ isPatientMyDoctorsLoading = val;
+ notifyListeners();
+ }
+
setAppointmentReminder(bool value, PatientAppointmentHistoryResponseModel item) {
int index = patientAppointmentsHistoryList.indexOf(item);
if (index != -1) {
@@ -253,4 +273,24 @@ class MyAppointmentsViewModel extends ChangeNotifier {
},
);
}
+
+ Future getPatientMyDoctors({Function(dynamic)? onSuccess, Function(String)? onError}) async {
+ final result = await myAppointmentsRepo.getPatientDoctorsList();
+
+ result.fold(
+ (failure) async => await errorHandlerService.handleError(failure: failure),
+ (apiResponse) {
+ if (apiResponse.messageStatus == 2) {
+ // dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {});
+ } else if (apiResponse.messageStatus == 1) {
+ patientMyDoctorsList = apiResponse.data!;
+ isPatientMyDoctorsLoading = false;
+ notifyListeners();
+ if (onSuccess != null) {
+ onSuccess(apiResponse);
+ }
+ }
+ },
+ );
+ }
}
diff --git a/lib/features/payfort/payfort_repo.dart b/lib/features/payfort/payfort_repo.dart
index 565422b..9f836d1 100644
--- a/lib/features/payfort/payfort_repo.dart
+++ b/lib/features/payfort/payfort_repo.dart
@@ -53,7 +53,7 @@ class PayfortRepoImp implements PayfortRepo {
} catch (e) {
failure = DataParsingFailure(e.toString());
}
- }, isAllowAny: true);
+ }, isAllowAny: true, isPaymentServices: true);
if (failure != null) return Left(failure!);
if (apiResponse == null) return Left(ServerFailure("Unknown error"));
return Right(apiResponse!);
@@ -80,7 +80,7 @@ class PayfortRepoImp implements PayfortRepo {
} catch (e) {
failure = DataParsingFailure(e.toString());
}
- }, isAllowAny: true);
+ }, isAllowAny: true, isPaymentServices: true);
if (failure != null) return Left(failure!);
if (apiResponse == null) return Left(ServerFailure("Unknown error"));
return Right(apiResponse!);
@@ -109,7 +109,7 @@ class PayfortRepoImp implements PayfortRepo {
} catch (e) {
failure = DataParsingFailure(e.toString());
}
- }, isAllowAny: true, isExternal: true);
+ }, isAllowAny: true, isExternal: true, isPaymentServices: true);
if (failure != null) return Left(failure!);
if (apiResponse == null) return Left(ServerFailure("Unknown error"));
return Right(apiResponse!);
@@ -139,7 +139,7 @@ class PayfortRepoImp implements PayfortRepo {
} catch (e) {
failure = DataParsingFailure(e.toString());
}
- }, isAllowAny: true);
+ }, isAllowAny: true, isPaymentServices: true);
if (failure != null) return Left(failure!);
if (apiResponse == null) return Left(ServerFailure("Unknown error"));
return Right(apiResponse!);
diff --git a/lib/generated/locale_keys.g.dart b/lib/generated/locale_keys.g.dart
index dc71850..8b7f021 100644
--- a/lib/generated/locale_keys.g.dart
+++ b/lib/generated/locale_keys.g.dart
@@ -780,6 +780,9 @@ abstract class LocaleKeys {
static const resultsPending = 'resultsPending';
static const resultsAvailable = 'resultsAvailable';
static const viewReport = 'viewReport';
+ static const checkAvailability = 'checkAvailability';
+ static const readInstructions = 'readInstructions';
+ static const searchLabReport = 'searchLabReport';
static const prescriptionDeliveryError = 'prescriptionDeliveryError';
static const receiveOtpToast = 'receiveOtpToast';
static const enterPhoneNumber = 'enterPhoneNumber';
@@ -802,12 +805,13 @@ abstract class LocaleKeys {
static const loginByOTP = 'loginByOTP';
static const guest = 'guest';
static const switchAccount = 'switchAccount';
- static const checkAvailability = 'checkAvailability';
- static const readInstructions = 'readInstructions';
- static const searchLabReport = 'searchLabReport';
- static const lastloginBy = 'lastloginBy';
- static const allSet ='allSet';
+ static const lastLoginBy = 'lastLoginBy';
+ static const allSet = 'allSet';
static const enableQuickLogin = 'enableQuickLogin';
static const enableMsg = 'enableMsg';
static const notNow = 'notNow';
+ static const pendingActivation = 'pendingActivation';
+ static const awaitingApproval = 'awaitingApproval';
+ static const ready = 'ready';
+
}
diff --git a/lib/main.dart b/lib/main.dart
index f76e372..24f5c36 100644
--- a/lib/main.dart
+++ b/lib/main.dart
@@ -9,6 +9,8 @@ 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/utils.dart';
import 'package:hmg_patient_app_new/features/authentication/authentication_view_model.dart';
+import 'package:hmg_patient_app_new/features/book_appointments/book_appointments_view_model.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/lab/lab_view_model.dart';
import 'package:hmg_patient_app_new/features/medical_file/medical_file_view_model.dart';
@@ -96,7 +98,10 @@ void main() async {
),
),
ChangeNotifierProvider(
- create: (_) => MedicalFileViewModel(),
+ create: (_) => MedicalFileViewModel(
+ medicalFileRepo: getIt(),
+ errorHandlerService: getIt(),
+ ),
),
ChangeNotifierProvider(
create: (_) => ProfileSettingsViewModel(),
@@ -113,6 +118,18 @@ void main() async {
errorHandlerService: getIt(),
),
),
+ ChangeNotifierProvider(
+ create: (_) => HabibWalletViewModel(
+ habibWalletRepo: getIt(),
+ errorHandlerService: getIt(),
+ ),
+ ),
+ ChangeNotifierProvider(
+ create: (_) => BookAppointmentsViewModel(
+ bookAppointmentsRepo: getIt(),
+ errorHandlerService: getIt(),
+ ),
+ ),
ChangeNotifierProvider(
create: (_) => AuthenticationViewModel(
authenticationRepo: getIt(),
diff --git a/lib/presentation/appointments/appointment_details_page.dart b/lib/presentation/appointments/appointment_details_page.dart
index 7188620..ee2a042 100644
--- a/lib/presentation/appointments/appointment_details_page.dart
+++ b/lib/presentation/appointments/appointment_details_page.dart
@@ -5,8 +5,6 @@ import 'package:flutter/cupertino.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_state.dart';
-import 'package:hmg_patient_app_new/core/dependencies.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';
@@ -20,6 +18,7 @@ import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
import 'package:hmg_patient_app_new/presentation/appointments/appointment_payment_page.dart';
import 'package:hmg_patient_app_new/presentation/appointments/widgets/appointment_checkin_bottom_sheet.dart';
import 'package:hmg_patient_app_new/presentation/appointments/widgets/appointment_doctor_card.dart';
+import 'package:hmg_patient_app_new/presentation/lab/collapsing_list_view.dart';
import 'package:hmg_patient_app_new/presentation/prescriptions/prescription_detail_page.dart';
import 'package:hmg_patient_app_new/presentation/prescriptions/prescriptions_list_page.dart';
import 'package:hmg_patient_app_new/theme/colors.dart';
@@ -58,338 +57,338 @@ class _AppointmentDetailsPageState extends State {
@override
Widget build(BuildContext context) {
- myAppointmentsViewModel = Provider.of(context);
- prescriptionsViewModel = Provider.of(context);
+ myAppointmentsViewModel = Provider.of(context, listen: false);
+ prescriptionsViewModel = Provider.of(context, listen: false);
return Scaffold(
backgroundColor: AppColors.bgScaffoldColor,
- appBar: AppBar(
- title: "Appointment Details".needTranslation.toText18(),
- backgroundColor: AppColors.bgScaffoldColor,
- ),
body: Column(
children: [
Expanded(
- child: SingleChildScrollView(
- child: Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- Row(
- mainAxisAlignment: MainAxisAlignment.spaceBetween,
- children: [
- "Appointment Details".needTranslation.toText20(isBold: true),
- if (AppointmentType.isArrived(widget.patientAppointmentHistoryResponseModel))
- CustomButton(
- text: "Report".needTranslation,
- onPressed: () {},
- backgroundColor: AppColors.secondaryLightRedColor,
- borderColor: AppColors.secondaryLightRedColor,
- textColor: AppColors.primaryRedColor,
- fontSize: 14,
- fontWeight: FontWeight.w500,
- borderRadius: 12,
- padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
- height: 40.h,
- iconSize: 16.h,
- icon: AppAssets.report_icon,
- iconColor: AppColors.primaryRedColor,
- )
- ],
- ),
- SizedBox(height: 24.h),
- AppointmentDoctorCard(
- patientAppointmentHistoryResponseModel: widget.patientAppointmentHistoryResponseModel,
- onAskDoctorTap: () {},
- onCancelTap: () async {
- showCommonBottomSheet(context,
- child: Utils.getLoadingWidget(),
- callBackFunc: (str) {},
- title: "",
- height: ResponsiveExtension.screenHeight * 0.3,
- isCloseButtonVisible: false,
- isDismissible: false,
- isFullScreen: false);
- await myAppointmentsViewModel.cancelAppointment(
- patientAppointmentHistoryResponseModel: widget.patientAppointmentHistoryResponseModel,
- onSuccess: (apiResponse) {
- Navigator.of(context).pop();
- showCommonBottomSheet(context,
- child: Utils.getSuccessWidget(loadingText: "Appointment Cancelled Successfully".needTranslation),
- callBackFunc: (str) {},
- title: "",
- height: ResponsiveExtension.screenHeight * 0.3,
- isCloseButtonVisible: false,
- isDismissible: false,
- isFullScreen: false,
- isSuccessDialog: true);
- });
- Navigator.of(context).pop();
- Navigator.of(context).pop();
- },
- onRescheduleTap: () {},
- ),
- SizedBox(height: 16.h),
- !AppointmentType.isArrived(widget.patientAppointmentHistoryResponseModel)
- ? Column(
- children: [
- Container(
- decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
- color: AppColors.whiteColor,
- borderRadius: 20.h,
- hasShadow: false,
+ child: CollapsingListView(
+ title: "Appointment Details".needTranslation,
+ report: () {},
+ child: SingleChildScrollView(
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ // Row(
+ // mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ // children: [
+ // "Appointment Details".needTranslation.toText20(isBold: true),
+ // if (AppointmentType.isArrived(widget.patientAppointmentHistoryResponseModel))
+ // CustomButton(
+ // text: "Report".needTranslation,
+ // onPressed: () {},
+ // backgroundColor: AppColors.secondaryLightRedColor,
+ // borderColor: AppColors.secondaryLightRedColor,
+ // textColor: AppColors.primaryRedColor,
+ // fontSize: 14,
+ // fontWeight: FontWeight.w500,
+ // borderRadius: 12,
+ // padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
+ // height: 40.h,
+ // iconSize: 16.h,
+ // icon: AppAssets.report_icon,
+ // iconColor: AppColors.primaryRedColor,
+ // )
+ // ],
+ // ),
+ // SizedBox(height: 24.h),
+ AppointmentDoctorCard(
+ patientAppointmentHistoryResponseModel: widget.patientAppointmentHistoryResponseModel,
+ onAskDoctorTap: () {},
+ onCancelTap: () async {
+ showCommonBottomSheet(context,
+ child: Utils.getLoadingWidget(),
+ callBackFunc: (str) {},
+ title: "",
+ height: ResponsiveExtension.screenHeight * 0.3,
+ isCloseButtonVisible: false,
+ isDismissible: false,
+ isFullScreen: false);
+ await myAppointmentsViewModel.cancelAppointment(
+ patientAppointmentHistoryResponseModel: widget.patientAppointmentHistoryResponseModel,
+ onSuccess: (apiResponse) {
+ Navigator.of(context).pop();
+ showCommonBottomSheet(context,
+ child: Utils.getSuccessWidget(loadingText: "Appointment Cancelled Successfully".needTranslation),
+ callBackFunc: (str) {},
+ title: "",
+ height: ResponsiveExtension.screenHeight * 0.3,
+ isCloseButtonVisible: false,
+ isDismissible: false,
+ isFullScreen: false,
+ isSuccessDialog: true);
+ });
+ Navigator.of(context).pop();
+ Navigator.of(context).pop();
+ },
+ onRescheduleTap: () {},
+ ),
+ SizedBox(height: 16.h),
+ !AppointmentType.isArrived(widget.patientAppointmentHistoryResponseModel)
+ ? Column(
+ children: [
+ Container(
+ decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
+ color: AppColors.whiteColor,
+ borderRadius: 20.h,
+ hasShadow: false,
+ ),
+ child: Padding(
+ padding: EdgeInsets.all(16.h),
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Row(
+ children: [
+ "Appointment Status".needTranslation.toText16(isBold: true),
+ ],
+ ),
+ SizedBox(height: 4.h),
+ (!AppointmentType.isConfirmed(widget.patientAppointmentHistoryResponseModel)
+ ? "Not Confirmed".needTranslation.toText12(color: AppColors.primaryRedColor, fontWeight: FontWeight.w500)
+ : "Confirmed".needTranslation.toText12(color: AppColors.successColor, fontWeight: FontWeight.w500)),
+ SizedBox(height: 16.h),
+ Stack(
+ children: [
+ ClipRRect(
+ clipBehavior: Clip.hardEdge,
+ borderRadius: BorderRadius.circular(24),
+ child: Image.network(
+ "https://maps.googleapis.com/maps/api/staticmap?center=${widget.patientAppointmentHistoryResponseModel.latitude},${widget.patientAppointmentHistoryResponseModel.longitude}&zoom=14&size=350x165&maptype=roadmap&markers=color:red%7C${widget.patientAppointmentHistoryResponseModel.latitude},${widget.patientAppointmentHistoryResponseModel.longitude}&key=AIzaSyB6TERnxIr0yJ3qG4ULBZbu0sAD4tGqtng",
+ fit: BoxFit.contain,
+ ),
+ ),
+ Positioned(
+ bottom: 0,
+ child: SizedBox(
+ width: MediaQuery.of(context).size.width * 0.785,
+ child: CustomButton(
+ text: "Get Directions".needTranslation,
+ onPressed: () {
+ MapsLauncher.launchCoordinates(double.parse(widget.patientAppointmentHistoryResponseModel.latitude!),
+ double.parse(widget.patientAppointmentHistoryResponseModel.longitude!), widget.patientAppointmentHistoryResponseModel.projectName);
+ },
+ backgroundColor: AppColors.textColor.withOpacity(0.8),
+ borderColor: AppointmentType.getNextActionButtonColor(widget.patientAppointmentHistoryResponseModel.nextAction).withOpacity(0.01),
+ textColor: AppColors.whiteColor,
+ fontSize: 14,
+ fontWeight: FontWeight.w500,
+ borderRadius: 12.h,
+ padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
+ height: 40.h,
+ icon: AppAssets.directions_icon,
+ iconColor: AppColors.whiteColor,
+ iconSize: 13.h,
+ ).paddingAll(12.h),
+ ),
+ ),
+ ],
+ ),
+ ],
+ ),
+ ),
),
- child: Padding(
- padding: EdgeInsets.all(16.h),
- child: Column(
- crossAxisAlignment: CrossAxisAlignment.start,
+ SizedBox(height: 16.h),
+ Container(
+ decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
+ color: AppColors.whiteColor,
+ borderRadius: 20.h,
+ hasShadow: false,
+ ),
+ child: Row(
+ mainAxisSize: MainAxisSize.max,
children: [
- Row(
+ Utils.buildSvgWithAssets(icon: AppAssets.prescription_reminder_icon, width: 35.h, height: 35.h),
+ SizedBox(width: 8.h),
+ Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
children: [
- "Appointment Status".needTranslation.toText16(isBold: true),
+ LocaleKeys.setReminder.tr(context: context).toText13(isBold: true),
+ "Notify me before the appointment".needTranslation.toText11(color: AppColors.textColorLight, weight: FontWeight.w500),
],
),
- SizedBox(height: 4.h),
- (!AppointmentType.isConfirmed(widget.patientAppointmentHistoryResponseModel)
- ? "Not Confirmed".needTranslation.toText12(color: AppColors.primaryRedColor, fontWeight: FontWeight.w500)
- : "Confirmed".needTranslation.toText12(color: AppColors.successColor, fontWeight: FontWeight.w500)),
- SizedBox(height: 16.h),
- Stack(
- children: [
- ClipRRect(
- clipBehavior: Clip.hardEdge,
- borderRadius: BorderRadius.circular(24),
- child: Image.network(
- "https://maps.googleapis.com/maps/api/staticmap?center=${widget.patientAppointmentHistoryResponseModel.latitude},${widget.patientAppointmentHistoryResponseModel.longitude}&zoom=14&size=350x165&maptype=roadmap&markers=color:red%7C${widget.patientAppointmentHistoryResponseModel.latitude},${widget.patientAppointmentHistoryResponseModel.longitude}&key=AIzaSyB6TERnxIr0yJ3qG4ULBZbu0sAD4tGqtng",
- fit: BoxFit.contain,
- ),
- ),
- Positioned(
- bottom: 0,
- child: SizedBox(
- width: MediaQuery.of(context).size.width * 0.785,
- child: CustomButton(
- text: "Get Directions".needTranslation,
- onPressed: () {
- MapsLauncher.launchCoordinates(double.parse(widget.patientAppointmentHistoryResponseModel.latitude!),
- double.parse(widget.patientAppointmentHistoryResponseModel.longitude!), widget.patientAppointmentHistoryResponseModel.projectName);
- },
- backgroundColor: AppColors.textColor.withOpacity(0.8),
- borderColor: AppointmentType.getNextActionButtonColor(widget.patientAppointmentHistoryResponseModel.nextAction).withOpacity(0.01),
- textColor: AppColors.whiteColor,
- fontSize: 14,
- fontWeight: FontWeight.w500,
- borderRadius: 12.h,
- padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
- height: 40.h,
- icon: AppAssets.directions_icon,
- iconColor: AppColors.whiteColor,
- iconSize: 13.h,
- ).paddingAll(12.h),
- ),
- ),
- ],
+ const Spacer(),
+ Switch(
+ activeColor: AppColors.successColor,
+ activeTrackColor: AppColors.successColor.withValues(alpha: .15),
+ value: widget.patientAppointmentHistoryResponseModel.hasReminder!,
+ onChanged: (newValue) {
+ setState(() {
+ myAppointmentsViewModel.setAppointmentReminder(newValue, widget.patientAppointmentHistoryResponseModel);
+ });
+ },
),
],
- ),
+ ).paddingSymmetrical(16.h, 16.h),
),
- ),
- SizedBox(height: 16.h),
- Container(
- decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
- color: AppColors.whiteColor,
- borderRadius: 20.h,
- hasShadow: false,
- ),
- child: Row(
- mainAxisSize: MainAxisSize.max,
+ SizedBox(height: 16.h),
+ ],
+ )
+ : Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ "Lab & Radiology".needTranslation.toText18(isBold: true),
+ SizedBox(height: 16.h),
+ GridView(
+ gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2, crossAxisSpacing: 13.h, mainAxisSpacing: 13.h, childAspectRatio: 7 / 6),
+ physics: NeverScrollableScrollPhysics(),
+ shrinkWrap: true,
children: [
- Utils.buildSvgWithAssets(icon: AppAssets.prescription_reminder_icon, width: 35.h, height: 35.h),
- SizedBox(width: 8.h),
- Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- LocaleKeys.setReminder.tr(context: context).toText13(isBold: true),
- "Notify me before the appointment".needTranslation.toText11(color: AppColors.textColorLight, weight: FontWeight.w500),
- ],
+ MedicalFileCard(
+ label: LocaleKeys.labResults.tr(context: context),
+ textColor: AppColors.blackColor,
+ backgroundColor: AppColors.whiteColor,
+ svgIcon: AppAssets.lab_result_icon,
+ iconSize: 40,
+ isLargeText: true,
),
- const Spacer(),
- Switch(
- activeColor: AppColors.successColor,
- activeTrackColor: AppColors.successColor.withValues(alpha: .15),
- value: widget.patientAppointmentHistoryResponseModel.hasReminder!,
- onChanged: (newValue) {
- setState(() {
- myAppointmentsViewModel.setAppointmentReminder(newValue, widget.patientAppointmentHistoryResponseModel);
- });
- },
+ MedicalFileCard(
+ label: LocaleKeys.radiology.tr(context: context),
+ textColor: AppColors.blackColor,
+ backgroundColor: AppColors.whiteColor,
+ svgIcon: AppAssets.radiology_icon,
+ iconSize: 40,
+ isLargeText: true,
),
],
- ).paddingSymmetrical(16.h, 16.h),
- ),
- SizedBox(height: 16.h),
- ],
- )
- : Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- "Lab & Radiology".needTranslation.toText18(isBold: true),
- SizedBox(height: 16.h),
- GridView(
- gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2, crossAxisSpacing: 13.h, mainAxisSpacing: 13.h, childAspectRatio: 7 / 6),
- physics: NeverScrollableScrollPhysics(),
- shrinkWrap: true,
- children: [
- MedicalFileCard(
- label: LocaleKeys.labResults.tr(context: context),
- textColor: AppColors.blackColor,
- backgroundColor: AppColors.whiteColor,
- svgIcon: AppAssets.lab_result_icon,
- iconSize: 40,
- isLargeText: true,
- ),
- MedicalFileCard(
- label: LocaleKeys.radiology.tr(context: context),
- textColor: AppColors.blackColor,
- backgroundColor: AppColors.whiteColor,
- svgIcon: AppAssets.radiology_icon,
- iconSize: 40,
- isLargeText: true,
- ),
- ],
- ),
- LocaleKeys.prescriptions.tr().toText18(isBold: true),
- SizedBox(height: 16.h),
- Consumer(builder: (context, prescriptionVM, child) {
- return prescriptionVM.isPrescriptionsDetailsLoading
- ? const MoviesShimmerWidget()
- : Container(
- decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
- color: Colors.white,
- borderRadius: 20.h,
- ),
- child: Padding(
- padding: EdgeInsets.all(16.h),
- child: Column(
- children: [
- ListView.separated(
- itemCount: prescriptionVM.prescriptionDetailsList.length,
- shrinkWrap: true,
- padding: const EdgeInsets.only(left: 0, right: 8),
- physics: NeverScrollableScrollPhysics(),
- itemBuilder: (context, index) {
- return AnimationConfiguration.staggeredList(
- position: index,
- duration: const Duration(milliseconds: 500),
- child: SlideAnimation(
- verticalOffset: 100.0,
- child: FadeInAnimation(
- child: Row(
- children: [
- Utils.buildSvgWithAssets(
- icon: AppAssets.prescription_item_icon,
- width: 40.h,
- height: 40.h,
- ),
- SizedBox(width: 8.h),
- Row(
- mainAxisSize: MainAxisSize.max,
- children: [
- Column(
- children: [
- SizedBox(width: 150.h, child: prescriptionVM.prescriptionDetailsList[index].itemDescription!.toText12(isBold: true, maxLine: 1)),
- SizedBox(
- width: 150.h,
- child:
- "Prescribed By: ${widget.patientAppointmentHistoryResponseModel.doctorTitle} ${widget.patientAppointmentHistoryResponseModel.doctorNameObj}"
- .needTranslation
- .toText10(weight: FontWeight.w500, color: AppColors.greyTextColor, letterSpacing: -0.4),
- ),
- ],
- ),
- SizedBox(width: 68.h),
- Utils.buildSvgWithAssets(
- icon: AppAssets.forward_arrow_icon,
- iconColor: AppColors.blackColor,
- width: 18.h,
- height: 13.h,
- fit: BoxFit.contain,
- ),
- ],
- ),
- ],
+ ),
+ LocaleKeys.prescriptions.tr().toText18(isBold: true),
+ SizedBox(height: 16.h),
+ Consumer(builder: (context, prescriptionVM, child) {
+ return prescriptionVM.isPrescriptionsDetailsLoading
+ ? const MoviesShimmerWidget()
+ : Container(
+ decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
+ color: Colors.white,
+ borderRadius: 20.h,
+ ),
+ child: Padding(
+ padding: EdgeInsets.all(16.h),
+ child: Column(
+ children: [
+ ListView.separated(
+ itemCount: prescriptionVM.prescriptionDetailsList.length,
+ shrinkWrap: true,
+ padding: const EdgeInsets.only(left: 0, right: 8),
+ physics: NeverScrollableScrollPhysics(),
+ itemBuilder: (context, index) {
+ return AnimationConfiguration.staggeredList(
+ position: index,
+ duration: const Duration(milliseconds: 500),
+ child: SlideAnimation(
+ verticalOffset: 100.0,
+ child: FadeInAnimation(
+ child: Row(
+ children: [
+ Utils.buildSvgWithAssets(
+ icon: AppAssets.prescription_item_icon,
+ width: 40.h,
+ height: 40.h,
+ ),
+ SizedBox(width: 8.h),
+ Row(
+ mainAxisSize: MainAxisSize.max,
+ children: [
+ Column(
+ children: [
+ SizedBox(width: 150.h, child: prescriptionVM.prescriptionDetailsList[index].itemDescription!.toText12(isBold: true, maxLine: 1)),
+ SizedBox(
+ width: 150.h,
+ child:
+ "Prescribed By: ${widget.patientAppointmentHistoryResponseModel.doctorTitle} ${widget.patientAppointmentHistoryResponseModel.doctorNameObj}"
+ .needTranslation
+ .toText10(weight: FontWeight.w500, color: AppColors.greyTextColor, letterSpacing: -0.4),
+ ),
+ ],
+ ),
+ SizedBox(width: 68.h),
+ Utils.buildSvgWithAssets(
+ icon: AppAssets.forward_arrow_icon,
+ iconColor: AppColors.blackColor,
+ width: 18.h,
+ height: 13.h,
+ fit: BoxFit.contain,
+ ),
+ ],
+ ),
+ ],
+ ),
),
),
+ );
+ },
+ separatorBuilder: (BuildContext cxt, int index) => SizedBox(height: 16.h),
+ ).onPress(() {
+ prescriptionVM.setPrescriptionsDetailsLoading();
+ Navigator.of(context).push(
+ FadePage(
+ page: PrescriptionDetailPage(prescriptionsResponseModel: getPrescriptionRequestModel()),
),
);
- },
- separatorBuilder: (BuildContext cxt, int index) => SizedBox(height: 16.h),
- ).onPress(() {
- prescriptionVM.setPrescriptionsDetailsLoading();
- Navigator.of(context).push(
- FadePage(
- page: PrescriptionDetailPage(prescriptionsResponseModel: getPrescriptionRequestModel()),
- ),
- );
- }),
- SizedBox(height: 16.h),
- const Divider(color: AppColors.dividerColor),
- SizedBox(height: 16.h),
- Row(
- children: [
- // Expanded(
- // child: CustomButton(
- // text: widget.prescriptionsResponseModel.isHomeMedicineDeliverySupported! ? LocaleKeys.resendOrder.tr(context: context) : LocaleKeys.prescriptionDeliveryError.tr(context: context),
- // onPressed: () {},
- // backgroundColor: AppColors.secondaryLightRedColor,
- // borderColor: AppColors.secondaryLightRedColor,
- // textColor: AppColors.primaryRedColor,
- // fontSize: 14,
- // fontWeight: FontWeight.w500,
- // borderRadius: 12.h,
- // height: 40.h,
- // icon: AppAssets.appointment_calendar_icon,
- // iconColor: AppColors.primaryRedColor,
- // iconSize: 16.h,
- // ),
- // ),
- // SizedBox(width: 16.h),
- Expanded(
- child: CustomButton(
- text: "All Prescriptions".needTranslation,
- onPressed: () {
- Navigator.of(context)
- .push(
- FadePage(
- page: PrescriptionsListPage(),
- ),
- )
- .then((val) {
- prescriptionsViewModel.setPrescriptionsDetailsLoading();
- prescriptionsViewModel.getPrescriptionDetails(getPrescriptionRequestModel());
- });
- },
- backgroundColor: AppColors.secondaryLightRedColor,
- borderColor: AppColors.secondaryLightRedColor,
- textColor: AppColors.primaryRedColor,
- fontSize: 14,
- fontWeight: FontWeight.w500,
- borderRadius: 12.h,
- height: 40.h,
- icon: AppAssets.requests,
- iconColor: AppColors.primaryRedColor,
- iconSize: 16.h,
+ }),
+ SizedBox(height: 16.h),
+ const Divider(color: AppColors.dividerColor),
+ SizedBox(height: 16.h),
+ Row(
+ children: [
+ // Expanded(
+ // child: CustomButton(
+ // text: widget.prescriptionsResponseModel.isHomeMedicineDeliverySupported! ? LocaleKeys.resendOrder.tr(context: context) : LocaleKeys.prescriptionDeliveryError.tr(context: context),
+ // onPressed: () {},
+ // backgroundColor: AppColors.secondaryLightRedColor,
+ // borderColor: AppColors.secondaryLightRedColor,
+ // textColor: AppColors.primaryRedColor,
+ // fontSize: 14,
+ // fontWeight: FontWeight.w500,
+ // borderRadius: 12.h,
+ // height: 40.h,
+ // icon: AppAssets.appointment_calendar_icon,
+ // iconColor: AppColors.primaryRedColor,
+ // iconSize: 16.h,
+ // ),
+ // ),
+ // SizedBox(width: 16.h),
+ Expanded(
+ child: CustomButton(
+ text: "All Prescriptions".needTranslation,
+ onPressed: () {
+ Navigator.of(context)
+ .push(
+ FadePage(
+ page: PrescriptionsListPage(),
+ ),
+ )
+ .then((val) {
+ prescriptionsViewModel.setPrescriptionsDetailsLoading();
+ prescriptionsViewModel.getPrescriptionDetails(getPrescriptionRequestModel());
+ });
+ },
+ backgroundColor: AppColors.secondaryLightRedColor,
+ borderColor: AppColors.secondaryLightRedColor,
+ textColor: AppColors.primaryRedColor,
+ fontSize: 14,
+ fontWeight: FontWeight.w500,
+ borderRadius: 12.h,
+ height: 40.h,
+ icon: AppAssets.requests,
+ iconColor: AppColors.primaryRedColor,
+ iconSize: 16.h,
+ ),
),
- ),
- ],
- ),
- ],
+ ],
+ ),
+ ],
+ ),
),
- ),
- );
- }),
- ],
- ),
- ],
- ).paddingSymmetrical(24.h, 24.h),
+ );
+ }),
+ ],
+ ),
+ ],
+ ).paddingSymmetrical(24.h, 24.h),
+ ),
),
),
Container(
diff --git a/lib/presentation/appointments/appointment_payment_page.dart b/lib/presentation/appointments/appointment_payment_page.dart
index 7f2ea9d..a617647 100644
--- a/lib/presentation/appointments/appointment_payment_page.dart
+++ b/lib/presentation/appointments/appointment_payment_page.dart
@@ -9,7 +9,6 @@ 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/dependencies.dart';
import 'package:hmg_patient_app_new/core/enums.dart';
-import 'package:hmg_patient_app_new/features/authentication/models/resp_models/authenticated_user_resp_model.dart';
import 'package:hmg_patient_app_new/features/payfort/models/apple_pay_request_insert_model.dart';
import 'package:hmg_patient_app_new/core/utils/size_utils.dart';
import 'package:hmg_patient_app_new/core/utils/utils.dart';
@@ -22,6 +21,7 @@ import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
import 'package:hmg_patient_app_new/presentation/appointments/my_appointments_page.dart';
import 'package:hmg_patient_app_new/presentation/home/navigation_screen.dart';
import 'package:hmg_patient_app_new/presentation/insurance/insurance_home_page.dart';
+import 'package:hmg_patient_app_new/presentation/lab/collapsing_list_view.dart';
import 'package:hmg_patient_app_new/services/cache_service.dart';
import 'package:hmg_patient_app_new/theme/colors.dart';
import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart';
@@ -55,6 +55,7 @@ class _AppointmentPaymentPageState extends State {
void initState() {
scheduleMicrotask(() {
payfortViewModel.initPayfortViewModel();
+ payfortViewModel.setIsApplePayConfigurationLoading(false);
myAppointmentsViewModel.getPatientShareAppointment(
widget.patientAppointmentHistoryResponseModel.projectID,
widget.patientAppointmentHistoryResponseModel.clinicID,
@@ -71,131 +72,131 @@ class _AppointmentPaymentPageState extends State {
payfortViewModel = Provider.of(context);
return Scaffold(
backgroundColor: AppColors.bgScaffoldColor,
- appBar: AppBar(
- title: "Appointment Payment".needTranslation.toText18(),
- backgroundColor: AppColors.bgScaffoldColor,
- ),
body: Consumer(builder: (context, myAppointmentsVM, child) {
- return myAppointmentsVM.isAppointmentPatientShareLoading
- ? const MoviesShimmerWidget().paddingAll(24.h)
- : Column(
- children: [
- Expanded(
- child: SingleChildScrollView(
- child: Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- "Appointment Payment".needTranslation.toText24(isBold: true).paddingSymmetrical(24.h, 0.h),
- SizedBox(height: 24.h),
- Container(
- decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
- color: AppColors.whiteColor,
- borderRadius: 20.h,
- hasShadow: false,
- ),
- child: Row(
- mainAxisSize: MainAxisSize.max,
- children: [
- Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- Image.asset(AppAssets.mada, width: 72.h, height: 25.h),
- SizedBox(height: 16.h),
- "Mada".needTranslation.toText16(isBold: true),
- ],
- ),
- SizedBox(width: 8.h),
- const Spacer(),
- Utils.buildSvgWithAssets(
- icon: AppAssets.forward_arrow_icon,
- iconColor: AppColors.blackColor,
- width: 18.h,
- height: 13.h,
- fit: BoxFit.contain,
- ),
- ],
- ).paddingSymmetrical(16.h, 16.h),
- ).paddingSymmetrical(24.h, 0.h).onPress(() {
- selectedPaymentMethod = "MADA";
- openPaymentURL("mada");
- }),
- SizedBox(height: 16.h),
- Container(
- decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
- color: AppColors.whiteColor,
- borderRadius: 20.h,
- hasShadow: false,
- ),
- child: Row(
- mainAxisSize: MainAxisSize.max,
- children: [
- Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- Row(
- children: [
- Image.asset(AppAssets.visa, width: 50.h, height: 50.h),
- SizedBox(width: 8.h),
- Image.asset(AppAssets.Mastercard, width: 40.h, height: 40.h),
- ],
- ),
- SizedBox(height: 16.h),
- "Visa or Mastercard".needTranslation.toText16(isBold: true),
- ],
- ),
- SizedBox(width: 8.h),
- const Spacer(),
- Utils.buildSvgWithAssets(
- icon: AppAssets.forward_arrow_icon,
- iconColor: AppColors.blackColor,
- width: 18.h,
- height: 13.h,
- fit: BoxFit.contain,
- ),
- ],
- ).paddingSymmetrical(16.h, 16.h),
- ).paddingSymmetrical(24.h, 0.h).onPress(() {
- selectedPaymentMethod = "VISA";
- openPaymentURL("visa");
- }),
- SizedBox(height: 16.h),
- Container(
- decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
- color: AppColors.whiteColor,
- borderRadius: 20.h,
- hasShadow: false,
- ),
- child: Row(
- mainAxisSize: MainAxisSize.max,
- children: [
- Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- Image.asset(AppAssets.tamara_en, width: 72.h, height: 25.h),
- SizedBox(height: 16.h),
- "Tamara".needTranslation.toText16(isBold: true),
- ],
- ),
- SizedBox(width: 8.h),
- const Spacer(),
- Utils.buildSvgWithAssets(
- icon: AppAssets.forward_arrow_icon,
- iconColor: AppColors.blackColor,
- width: 18.h,
- height: 13.h,
- fit: BoxFit.contain,
- ),
- ],
- ).paddingSymmetrical(16.h, 16.h),
- ).paddingSymmetrical(24.h, 0.h).onPress(() {
- selectedPaymentMethod = "TAMARA";
- openPaymentURL("tamara");
- }),
- ],
- ),
- ),
- ),
- Container(
+ return Column(
+ children: [
+ Expanded(
+ child: CollapsingListView(
+ title: "Appointment Payment".needTranslation,
+ child: SingleChildScrollView(
+ child: myAppointmentsVM.isAppointmentPatientShareLoading
+ ? const MoviesShimmerWidget().paddingAll(24.h)
+ : Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ SizedBox(height: 24.h),
+ Container(
+ decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
+ color: AppColors.whiteColor,
+ borderRadius: 20.h,
+ hasShadow: false,
+ ),
+ child: Row(
+ mainAxisSize: MainAxisSize.max,
+ children: [
+ Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Image.asset(AppAssets.mada, width: 72.h, height: 25.h),
+ SizedBox(height: 16.h),
+ "Mada".needTranslation.toText16(isBold: true),
+ ],
+ ),
+ SizedBox(width: 8.h),
+ const Spacer(),
+ Utils.buildSvgWithAssets(
+ icon: AppAssets.forward_arrow_icon,
+ iconColor: AppColors.blackColor,
+ width: 18.h,
+ height: 13.h,
+ fit: BoxFit.contain,
+ ),
+ ],
+ ).paddingSymmetrical(16.h, 16.h),
+ ).paddingSymmetrical(24.h, 0.h).onPress(() {
+ selectedPaymentMethod = "MADA";
+ openPaymentURL("mada");
+ }),
+ SizedBox(height: 16.h),
+ Container(
+ decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
+ color: AppColors.whiteColor,
+ borderRadius: 20.h,
+ hasShadow: false,
+ ),
+ child: Row(
+ mainAxisSize: MainAxisSize.max,
+ children: [
+ Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Row(
+ children: [
+ Image.asset(AppAssets.visa, width: 50.h, height: 50.h),
+ SizedBox(width: 8.h),
+ Image.asset(AppAssets.Mastercard, width: 40.h, height: 40.h),
+ ],
+ ),
+ SizedBox(height: 16.h),
+ "Visa or Mastercard".needTranslation.toText16(isBold: true),
+ ],
+ ),
+ SizedBox(width: 8.h),
+ const Spacer(),
+ Utils.buildSvgWithAssets(
+ icon: AppAssets.forward_arrow_icon,
+ iconColor: AppColors.blackColor,
+ width: 18.h,
+ height: 13.h,
+ fit: BoxFit.contain,
+ ),
+ ],
+ ).paddingSymmetrical(16.h, 16.h),
+ ).paddingSymmetrical(24.h, 0.h).onPress(() {
+ selectedPaymentMethod = "VISA";
+ openPaymentURL("visa");
+ }),
+ SizedBox(height: 16.h),
+ Container(
+ decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
+ color: AppColors.whiteColor,
+ borderRadius: 20.h,
+ hasShadow: false,
+ ),
+ child: Row(
+ mainAxisSize: MainAxisSize.max,
+ children: [
+ Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Image.asset(AppAssets.tamara_en, width: 72.h, height: 25.h),
+ SizedBox(height: 16.h),
+ "Tamara".needTranslation.toText16(isBold: true),
+ ],
+ ),
+ SizedBox(width: 8.h),
+ const Spacer(),
+ Utils.buildSvgWithAssets(
+ icon: AppAssets.forward_arrow_icon,
+ iconColor: AppColors.blackColor,
+ width: 18.h,
+ height: 13.h,
+ fit: BoxFit.contain,
+ ),
+ ],
+ ).paddingSymmetrical(16.h, 16.h),
+ ).paddingSymmetrical(24.h, 0.h).onPress(() {
+ selectedPaymentMethod = "TAMARA";
+ openPaymentURL("tamara");
+ }),
+ ],
+ ),
+ ),
+ ),
+ ),
+ myAppointmentsVM.isAppointmentPatientShareLoading
+ ? SizedBox.shrink()
+ : Container(
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.whiteColor,
borderRadius: 24.h,
@@ -283,7 +284,7 @@ class _AppointmentPaymentPageState extends State {
height: 80.h,
fit: BoxFit.contain,
).paddingSymmetrical(24.h, 0.h).onPress(() {
- payfortVM.setIsApplePayConfigurationLoading(true);
+ // payfortVM.setIsApplePayConfigurationLoading(true);
startApplePay();
}),
SizedBox(height: 12.h),
@@ -291,8 +292,8 @@ class _AppointmentPaymentPageState extends State {
);
}),
),
- ],
- );
+ ],
+ );
}),
);
}
@@ -344,62 +345,74 @@ class _AppointmentPaymentPageState extends State {
// updateTamaraRequestStatus("Failed", "00", Utils.getAppointmentTransID(appo.projectID, appo.clinicID, appo.appointmentNo), tamaraOrderID, num.parse(selectedInstallments), appo);
// }
} else {
- showCommonBottomSheet(context,
- child: Utils.getLoadingWidget(), callBackFunc: (str) {}, title: "", height: ResponsiveExtension.screenHeight * 0.3, isCloseButtonVisible: false, isDismissible: false, isFullScreen: false);
- await payfortViewModel.checkPaymentStatus(
- transactionID: transID,
- onSuccess: (apiResponse) async {
- print(apiResponse.data);
- if (payfortViewModel.payfortCheckPaymentStatusResponseModel!.responseMessage!.toLowerCase() == "success") {
- await myAppointmentsViewModel.createAdvancePayment(
- paymentMethodName: selectedPaymentMethod,
- projectID: widget.patientAppointmentHistoryResponseModel.projectID,
- clinicID: widget.patientAppointmentHistoryResponseModel.clinicID,
- appointmentNo: widget.patientAppointmentHistoryResponseModel.appointmentNo.toString(),
- payedAmount: payfortViewModel.payfortCheckPaymentStatusResponseModel!.amount!,
- paymentReference: payfortViewModel.payfortCheckPaymentStatusResponseModel!.fortId!,
- patientID: "4767477",
- patientType: 1,
- onSuccess: (value) async {
- print(value);
- await myAppointmentsViewModel.addAdvanceNumberRequest(
- advanceNumber: Utils.isVidaPlusProject(appState, widget.patientAppointmentHistoryResponseModel.projectID)
- ? value.data['OnlineCheckInAppointments'][0]['AdvanceNumber_VP'].toString()
- : value.data['OnlineCheckInAppointments'][0]['AdvanceNumber'].toString(),
- paymentReference: payfortViewModel.payfortCheckPaymentStatusResponseModel!.fortId!,
- appointmentNo: widget.patientAppointmentHistoryResponseModel.appointmentNo.toString(),
- onSuccess: (value) async {
- if (widget.patientAppointmentHistoryResponseModel.isLiveCareAppointment!) {
- //TODO: Implement LiveCare Check-In API Call
- } else {
- await myAppointmentsViewModel.generateAppointmentQR(
- clinicID: widget.patientAppointmentHistoryResponseModel.clinicID,
- projectID: widget.patientAppointmentHistoryResponseModel.projectID,
- appointmentNo: widget.patientAppointmentHistoryResponseModel.appointmentNo.toString(),
- isFollowUp: myAppointmentsViewModel.patientAppointmentShareResponseModel!.isFollowup!,
- onSuccess: (apiResponse) {
- Future.delayed(Duration(milliseconds: 500), () {
- Navigator.of(context).pop();
- Navigator.pushAndRemoveUntil(
- context,
- FadePage(
- page: LandingNavigation(),
- ),
- (r) => false);
- Navigator.of(context).push(
- FadePage(page: MyAppointmentsPage()),
- );
- });
- });
- }
- });
- });
- } else {}
- });
+ checkPaymentStatus();
// checkPaymentStatus(appo);
}
}
+ void checkPaymentStatus() async {
+ showCommonBottomSheet(context,
+ child: Utils.getLoadingWidget(), callBackFunc: (str) {}, title: "", height: ResponsiveExtension.screenHeight * 0.3, isCloseButtonVisible: false, isDismissible: false, isFullScreen: false);
+ await payfortViewModel.checkPaymentStatus(
+ transactionID: transID,
+ onSuccess: (apiResponse) async {
+ print(apiResponse.data);
+ if (payfortViewModel.payfortCheckPaymentStatusResponseModel!.responseMessage!.toLowerCase() == "success") {
+ await myAppointmentsViewModel.createAdvancePayment(
+ paymentMethodName: selectedPaymentMethod,
+ projectID: widget.patientAppointmentHistoryResponseModel.projectID,
+ clinicID: widget.patientAppointmentHistoryResponseModel.clinicID,
+ appointmentNo: widget.patientAppointmentHistoryResponseModel.appointmentNo.toString(),
+ payedAmount: payfortViewModel.payfortCheckPaymentStatusResponseModel!.amount!,
+ paymentReference: payfortViewModel.payfortCheckPaymentStatusResponseModel!.fortId!,
+ patientID: "4767477",
+ patientType: 1,
+ onSuccess: (value) async {
+ print(value);
+ await myAppointmentsViewModel.addAdvanceNumberRequest(
+ advanceNumber: Utils.isVidaPlusProject(widget.patientAppointmentHistoryResponseModel.projectID)
+ ? value.data['OnlineCheckInAppointments'][0]['AdvanceNumber_VP'].toString()
+ : value.data['OnlineCheckInAppointments'][0]['AdvanceNumber'].toString(),
+ paymentReference: payfortViewModel.payfortCheckPaymentStatusResponseModel!.fortId!,
+ appointmentNo: widget.patientAppointmentHistoryResponseModel.appointmentNo.toString(),
+ onSuccess: (value) async {
+ if (widget.patientAppointmentHistoryResponseModel.isLiveCareAppointment!) {
+ //TODO: Implement LiveCare Check-In API Call
+ } else {
+ await myAppointmentsViewModel.generateAppointmentQR(
+ clinicID: widget.patientAppointmentHistoryResponseModel.clinicID,
+ projectID: widget.patientAppointmentHistoryResponseModel.projectID,
+ appointmentNo: widget.patientAppointmentHistoryResponseModel.appointmentNo.toString(),
+ isFollowUp: myAppointmentsViewModel.patientAppointmentShareResponseModel!.isFollowup!,
+ onSuccess: (apiResponse) {
+ Future.delayed(Duration(milliseconds: 500), () {
+ Navigator.of(context).pop();
+ Navigator.pushAndRemoveUntil(
+ context,
+ FadePage(
+ page: LandingNavigation(),
+ ),
+ (r) => false);
+ Navigator.of(context).push(
+ FadePage(page: MyAppointmentsPage()),
+ );
+ });
+ });
+ }
+ });
+ });
+ } else {
+ showCommonBottomSheetWithoutHeight(
+ context,
+ child: Utils.getErrorWidget(loadingText: "Payment Failed! Please try again.".needTranslation),
+ callBackFunc: () {},
+ isFullScreen: false,
+ isCloseButtonVisible: true,
+ );
+ }
+ });
+ }
+
openPaymentURL(String paymentMethod) {
browser = MyInAppBrowser(onExitCallback: onBrowserExit, onLoadStartCallback: onBrowserLoadStart, context: context);
transID = Utils.getAppointmentTransID(
@@ -433,6 +446,8 @@ class _AppointmentPaymentPageState extends State {
}
startApplePay() async {
+ showCommonBottomSheet(context,
+ child: Utils.getLoadingWidget(), callBackFunc: (str) {}, title: "", height: ResponsiveExtension.screenHeight * 0.3, isCloseButtonVisible: false, isDismissible: false, isFullScreen: false);
transID = Utils.getAppointmentTransID(
widget.patientAppointmentHistoryResponseModel.projectID,
widget.patientAppointmentHistoryResponseModel.clinicID,
@@ -447,8 +462,7 @@ class _AppointmentPaymentPageState extends State {
applePayInsertRequest.clientRequestID = transID;
applePayInsertRequest.clinicID = widget.patientAppointmentHistoryResponseModel.clinicID;
- //TODO: Need to pass dynamic params to the payment request instead of static values
- applePayInsertRequest.currency = "SAR";
+ applePayInsertRequest.currency = appState.getAuthenticatedUser()!.outSa! == 0 ? "SAR" : "AED";
applePayInsertRequest.customerEmail = "CustID_${appState.getAuthenticatedUser()!.patientId.toString()}@HMG.com";
applePayInsertRequest.customerID = appState.getAuthenticatedUser()!.patientId.toString();
applePayInsertRequest.customerName = "${appState.getAuthenticatedUser()!.firstName} ${appState.getAuthenticatedUser()!.lastName}";
@@ -460,8 +474,8 @@ class _AppointmentPaymentPageState extends State {
applePayInsertRequest.serviceID = ServiceTypeEnum.appointmentPayment.getIdFromServiceEnum().toString();
applePayInsertRequest.channelID = 3;
applePayInsertRequest.patientID = appState.getAuthenticatedUser()!.patientId.toString();
- applePayInsertRequest.patientTypeID = 1;
- applePayInsertRequest.patientOutSA = 0;
+ applePayInsertRequest.patientTypeID = appState.getAuthenticatedUser()!.patientType;
+ applePayInsertRequest.patientOutSA = appState.getAuthenticatedUser()!.outSa;
applePayInsertRequest.appointmentDate = widget.patientAppointmentHistoryResponseModel.appointmentDate;
applePayInsertRequest.appointmentNo = widget.patientAppointmentHistoryResponseModel.appointmentNo;
applePayInsertRequest.orderDescription = "Appointment Payment";
@@ -472,7 +486,7 @@ class _AppointmentPaymentPageState extends State {
applePayInsertRequest.isSchedule = widget.patientAppointmentHistoryResponseModel.isLiveCareAppointment! ? "1" : "0";
applePayInsertRequest.language = appState.isArabic() ? 'ar' : 'en';
applePayInsertRequest.languageID = appState.isArabic() ? 1 : 2;
- applePayInsertRequest.userName = 3628599;
+ applePayInsertRequest.userName = appState.getAuthenticatedUser()!.patientId;
applePayInsertRequest.responseContinueURL = "http://hmg.com/Documents/success.html";
applePayInsertRequest.backClickUrl = "http://hmg.com/Documents/success.html";
applePayInsertRequest.paymentOption = "ApplePay";
@@ -499,12 +513,22 @@ class _AppointmentPaymentPageState extends State {
merchantIdentifier: payfortViewModel.payfortProjectDetailsRespModel!.merchantIdentifier,
applePayAccessCode: payfortViewModel.payfortProjectDetailsRespModel!.accessCode,
applePayShaRequestPhrase: payfortViewModel.payfortProjectDetailsRespModel!.shaRequest,
- currency: "SAR",
+ currency: appState.getAuthenticatedUser()!.outSa! == 0 ? "SAR" : "AED",
onFailed: (failureResult) async {
log("failureResult: ${failureResult.message.toString()}");
+ Navigator.of(context).pop();
+ showCommonBottomSheetWithoutHeight(
+ context,
+ child: Utils.getErrorWidget(loadingText: failureResult.message.toString()),
+ callBackFunc: () {},
+ isFullScreen: false,
+ isCloseButtonVisible: true,
+ );
},
onSucceeded: (successResult) async {
+ Navigator.of(context).pop();
log("successResult: ${successResult.responseMessage.toString()}");
+ checkPaymentStatus();
},
// projectId: appo.projectID,
// serviceTypeEnum: ServiceTypeEnum.appointmentPayment,
diff --git a/lib/presentation/appointments/my_appointments_page.dart b/lib/presentation/appointments/my_appointments_page.dart
index 4a3a46e..5a3205d 100644
--- a/lib/presentation/appointments/my_appointments_page.dart
+++ b/lib/presentation/appointments/my_appointments_page.dart
@@ -1,17 +1,14 @@
import 'dart:async';
-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_state.dart';
-import 'package:hmg_patient_app_new/core/dependencies.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';
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/appointments/widgets/appointment_card.dart';
+import 'package:hmg_patient_app_new/presentation/lab/collapsing_list_view.dart';
import 'package:hmg_patient_app_new/theme/colors.dart';
import 'package:hmg_patient_app_new/widgets/custom_tab_bar.dart';
import 'package:hmg_patient_app_new/widgets/shimmer/movies_shimmer_widget.dart';
@@ -38,39 +35,33 @@ class _MyAppointmentsPageState extends State {
@override
Widget build(BuildContext context) {
- myAppointmentsViewModel = Provider.of(context);
+ myAppointmentsViewModel = Provider.of(context, listen: false);
return Scaffold(
backgroundColor: AppColors.bgScaffoldColor,
- appBar: AppBar(
- title: "Appointments List".needTranslation.toText18(),
- backgroundColor: AppColors.bgScaffoldColor,
- ),
- body: SingleChildScrollView(
- child: Column(
- children: [
- Row(
- mainAxisAlignment: MainAxisAlignment.spaceBetween,
- children: [
- "Appointments List".needTranslation.toText24(isBold: true),
- ],
- ).paddingSymmetrical(24.h, 24.h),
- CustomTabBar(
- activeTextColor: Color(0xffED1C2B),
- activeBackgroundColor: Color(0xffED1C2B).withValues(alpha: .1),
- tabs: [
- CustomTabBarModel(null, "All Appt.".needTranslation),
- CustomTabBarModel(null, "Upcoming".needTranslation),
- CustomTabBarModel(null, "Completed".needTranslation),
- ],
- onTabChange: (index) {
- print(index);
- myAppointmentsViewModel.onTabChange(index);
- },
- ).paddingSymmetrical(24.h, 0.h),
- Consumer(builder: (context, myAppointmentsVM, child) {
- return getSelectedTabData(myAppointmentsVM.selectedTabIndex, myAppointmentsVM);
- }),
- ],
+ body: CollapsingListView(
+ title: "Appointments List".needTranslation,
+ child: SingleChildScrollView(
+ child: Column(
+ children: [
+ SizedBox(height: 16.h),
+ CustomTabBar(
+ activeTextColor: Color(0xffED1C2B),
+ activeBackgroundColor: Color(0xffED1C2B).withValues(alpha: .1),
+ tabs: [
+ CustomTabBarModel(null, "All Appt.".needTranslation),
+ CustomTabBarModel(null, "Upcoming".needTranslation),
+ CustomTabBarModel(null, "Completed".needTranslation),
+ ],
+ onTabChange: (index) {
+ print(index);
+ myAppointmentsViewModel.onTabChange(index);
+ },
+ ).paddingSymmetrical(24.h, 0.h),
+ Consumer(builder: (context, myAppointmentsVM, child) {
+ return getSelectedTabData(myAppointmentsVM.selectedTabIndex, myAppointmentsVM);
+ }),
+ ],
+ ),
),
),
);
@@ -83,9 +74,9 @@ class _MyAppointmentsPageState extends State {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
- SizedBox(height: 24.h),
// Expandable list
ListView.separated(
+ padding: EdgeInsets.only(top: 24.h),
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
itemCount: myAppointmentsVM.isMyAppointmentsLoading
@@ -106,7 +97,6 @@ class _MyAppointmentsPageState extends State {
child: AnimatedContainer(
duration: Duration(milliseconds: 300),
curve: Curves.easeInOut,
- margin: EdgeInsets.symmetric(vertical: 8.h),
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24.h, hasShadow: true),
child: AppointmentCard(
patientAppointmentHistoryResponseModel: myAppointmentsVM.patientAppointmentsHistoryList[index],
@@ -127,7 +117,6 @@ class _MyAppointmentsPageState extends State {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
- SizedBox(height: 24.h),
// Expandable list
ListView.separated(
shrinkWrap: true,
@@ -171,7 +160,6 @@ class _MyAppointmentsPageState extends State {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
- SizedBox(height: 24.h),
// Expandable list
ListView.separated(
shrinkWrap: true,
@@ -179,32 +167,32 @@ class _MyAppointmentsPageState extends State {
itemCount: myAppointmentsVM.isMyAppointmentsLoading
? 5
: myAppointmentsVM.patientArrivedAppointmentsHistoryList.isNotEmpty
- ? myAppointmentsVM.patientArrivedAppointmentsHistoryList.length
- : 1,
+ ? myAppointmentsVM.patientArrivedAppointmentsHistoryList.length
+ : 1,
itemBuilder: (context, index) {
return myAppointmentsVM.isMyAppointmentsLoading
? const MoviesShimmerWidget().paddingSymmetrical(24.h, 0.h)
: myAppointmentsVM.patientArrivedAppointmentsHistoryList.isNotEmpty
- ? AnimationConfiguration.staggeredList(
- position: index,
- duration: const Duration(milliseconds: 500),
- child: SlideAnimation(
- verticalOffset: 100.0,
- child: FadeInAnimation(
- child: AnimatedContainer(
- duration: Duration(milliseconds: 300),
- curve: Curves.easeInOut,
- margin: EdgeInsets.symmetric(vertical: 8.h),
- decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24.h, hasShadow: true),
- child: AppointmentCard(
- patientAppointmentHistoryResponseModel: myAppointmentsVM.patientArrivedAppointmentsHistoryList[index],
- myAppointmentsViewModel: myAppointmentsViewModel,
- ),
- ).paddingSymmetrical(24.h, 0.h),
- ),
- ),
- )
- : Utils.getNoDataWidget(context);
+ ? AnimationConfiguration.staggeredList(
+ position: index,
+ duration: const Duration(milliseconds: 500),
+ child: SlideAnimation(
+ verticalOffset: 100.0,
+ child: FadeInAnimation(
+ child: AnimatedContainer(
+ duration: Duration(milliseconds: 300),
+ curve: Curves.easeInOut,
+ margin: EdgeInsets.symmetric(vertical: 8.h),
+ decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24.h, hasShadow: true),
+ child: AppointmentCard(
+ patientAppointmentHistoryResponseModel: myAppointmentsVM.patientArrivedAppointmentsHistoryList[index],
+ myAppointmentsViewModel: myAppointmentsViewModel,
+ ),
+ ).paddingSymmetrical(24.h, 0.h),
+ ),
+ ),
+ )
+ : Utils.getNoDataWidget(context);
},
separatorBuilder: (BuildContext cxt, int index) => SizedBox(height: 16.h),
),
diff --git a/lib/presentation/appointments/my_doctors_page.dart b/lib/presentation/appointments/my_doctors_page.dart
new file mode 100644
index 0000000..89b120c
--- /dev/null
+++ b/lib/presentation/appointments/my_doctors_page.dart
@@ -0,0 +1,160 @@
+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/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';
+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/lab/collapsing_list_view.dart';
+import 'package:hmg_patient_app_new/theme/colors.dart';
+import 'package:provider/provider.dart';
+
+import '../../widgets/chip/app_custom_chip_widget.dart';
+
+class MyDoctorsPage extends StatelessWidget {
+ MyDoctorsPage({super.key});
+
+ late MyAppointmentsViewModel myAppointmentsViewModel;
+
+ @override
+ Widget build(BuildContext context) {
+ myAppointmentsViewModel = Provider.of(context, listen: false);
+ return Scaffold(
+ backgroundColor: AppColors.bgScaffoldColor,
+ body: CollapsingListView(
+ title: LocaleKeys.myDoctor.tr(context: context),
+ child: SingleChildScrollView(
+ child: Consumer(builder: (context, myAppointmentsVM, child) {
+ return Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ SizedBox(height: 16.h),
+ ListView.separated(
+ scrollDirection: Axis.vertical,
+ itemCount: myAppointmentsVM.isPatientMyDoctorsLoading ? 5 : myAppointmentsVM.patientMyDoctorsList.length,
+ shrinkWrap: true,
+ physics: NeverScrollableScrollPhysics(),
+ padding: EdgeInsets.only(left: 24.h, right: 24.h),
+ itemBuilder: (context, index) {
+ return myAppointmentsVM.isPatientMyDoctorsLoading
+ ? Container(
+ decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
+ color: AppColors.whiteColor,
+ borderRadius: 20.h,
+ hasShadow: true,
+ ),
+ child: Padding(
+ padding: EdgeInsets.all(14.h),
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Row(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Image.network(
+ "https://hmgwebservices.com/Images/MobileImages/DUBAI/unkown_female.png",
+ width: 63.h,
+ height: 63.h,
+ fit: BoxFit.fill,
+ ).circle(100).toShimmer2(isShow: true),
+ SizedBox(width: 16.h),
+ Expanded(
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ "Dr John Smith".toText16(isBold: true).toShimmer2(isShow: true),
+ SizedBox(height: 8.h),
+ Wrap(
+ direction: Axis.horizontal,
+ spacing: 3.h,
+ runSpacing: 4.h,
+ children: [
+ AppCustomChipWidget(labelText: "").toShimmer2(isShow: true, width: 16.h),
+ AppCustomChipWidget(labelText: "").toShimmer2(isShow: true, width: 16.h),
+ ],
+ ),
+ ],
+ ),
+ ),
+ ],
+ ),
+ ],
+ ),
+ ),
+ )
+ : AnimationConfiguration.staggeredList(
+ position: index,
+ duration: const Duration(milliseconds: 1000),
+ child: SlideAnimation(
+ verticalOffset: 100.0,
+ child: FadeInAnimation(
+ child: Container(
+ decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
+ color: AppColors.whiteColor,
+ borderRadius: 20.h,
+ hasShadow: true,
+ ),
+ child: Padding(
+ padding: EdgeInsets.all(14.h),
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Row(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Image.network(
+ myAppointmentsVM.patientMyDoctorsList[index].doctorImageURL!,
+ width: 63.h,
+ height: 63.h,
+ fit: BoxFit.fill,
+ ).circle(100).toShimmer2(isShow: false),
+ SizedBox(width: 16.h),
+ Expanded(
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ (myAppointmentsVM.patientMyDoctorsList[index].doctorName).toString().toText16(isBold: true).toShimmer2(isShow: false),
+ SizedBox(height: 8.h),
+ Wrap(
+ direction: Axis.horizontal,
+ spacing: 3.h,
+ runSpacing: 4.h,
+ children: [
+ AppCustomChipWidget(labelText: myAppointmentsVM.patientMyDoctorsList[index].clinicName).toShimmer2(isShow: false, width: 16.h),
+ AppCustomChipWidget(labelText: myAppointmentsVM.patientMyDoctorsList[index].projectName).toShimmer2(isShow: false, width: 16.h),
+ ],
+ ),
+ ],
+ ),
+ ),
+ ],
+ ),
+ Row(
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ children: [
+ "".toText16(),
+ Utils.buildSvgWithAssets(icon: AppAssets.forward_arrow_icon, width: 15.h, height: 15.h, fit: BoxFit.contain, iconColor: AppColors.textColor),
+ ],
+ ),
+ ],
+ ),
+ ),
+ ),
+ ),
+ ),
+ );
+ },
+ separatorBuilder: (BuildContext cxt, int index) => SizedBox(height: 16.h),
+ ),
+ SizedBox(height: 60.h),
+ ],
+ );
+ }),
+ ),
+ ),
+ );
+ }
+}
diff --git a/lib/presentation/appointments/widgets/appointment_card.dart b/lib/presentation/appointments/widgets/appointment_card.dart
index e9babeb..815443e 100644
--- a/lib/presentation/appointments/widgets/appointment_card.dart
+++ b/lib/presentation/appointments/widgets/appointment_card.dart
@@ -142,7 +142,7 @@ class _AppointmentCardState extends State {
Wrap(
direction: Axis.horizontal,
spacing: 3.h,
- runSpacing: -8.h,
+ runSpacing: 4.h,
children: [
AppCustomChipWidget(labelText: widget.patientAppointmentHistoryResponseModel.clinicName!),
AppCustomChipWidget(labelText: widget.patientAppointmentHistoryResponseModel.projectName!),
diff --git a/lib/presentation/appointments/widgets/appointment_doctor_card.dart b/lib/presentation/appointments/widgets/appointment_doctor_card.dart
index e6d7338..d7b0f68 100644
--- a/lib/presentation/appointments/widgets/appointment_doctor_card.dart
+++ b/lib/presentation/appointments/widgets/appointment_doctor_card.dart
@@ -51,7 +51,7 @@ class AppointmentDoctorCard extends StatelessWidget {
Wrap(
direction: Axis.horizontal,
spacing: 3.h,
- runSpacing: -8.h,
+ runSpacing: 4.h,
children: [
AppCustomChipWidget(labelText: patientAppointmentHistoryResponseModel.clinicName!),
AppCustomChipWidget(labelText: patientAppointmentHistoryResponseModel.projectName!),
diff --git a/lib/presentation/authentication/register.dart b/lib/presentation/authentication/register.dart
index f238582..efb0a18 100644
--- a/lib/presentation/authentication/register.dart
+++ b/lib/presentation/authentication/register.dart
@@ -213,7 +213,7 @@ class _RegisterNew extends State {
countryCode: authVM.selectedCountrySignup.countryCode,
initialPhoneNumber: "",
textController: authVM.phoneNumberController,
- isEnableCountryDropdown: true,
+ isEnableCountryDropdown: false,
onCountryChange: authVM.onCountryChange,
onChange: authVM.onPhoneNumberChange,
buttons: [
diff --git a/lib/presentation/authentication/register_step2.dart b/lib/presentation/authentication/register_step2.dart
index bd23be1..d7071a4 100644
--- a/lib/presentation/authentication/register_step2.dart
+++ b/lib/presentation/authentication/register_step2.dart
@@ -46,7 +46,7 @@ class _RegisterNew extends State {
appBar: CustomAppBar(
onBackPressed: () {
Navigator.of(context).pop();
- authVM!.clearDefaultInputValues();
+ // authVM!.clearDefaultInputValues();
},
onLanguageChanged: (lang) {},
hideLogoAndLang: true,
@@ -217,15 +217,14 @@ class _RegisterNew extends State {
TextInputWidget(
labelText: LocaleKeys.mobileNumber.tr(),
hintText: (appState.getUserRegistrationPayload.patientMobileNumber.toString() ?? ""),
- controller: authVM!.phoneNumberController,
- isEnable: true,
+ controller: null,
+ isEnable: false,
prefix: null,
isAllowRadius: false,
isBorderAllowed: false,
isAllowLeadingIcon: true,
isReadOnly: true,
- leadingIcon: AppAssets.call,
- onChange: (value) {})
+ leadingIcon: AppAssets.call)
.paddingSymmetrical(0.h, 16.h),
Divider(
height: 1,
@@ -233,15 +232,15 @@ class _RegisterNew extends State {
),
TextInputWidget(
labelText: LocaleKeys.dob.tr(),
- hintText: authVM!.isUserFromUAE() ? appState.getUserRegistrationPayload.dob! : (appState.getNHICUserData.dateOfBirth ?? ""),
- controller: authVM!.dobController,
- isEnable: authVM!.isUserFromUAE() ? true : false,
+ hintText: authVM!.isUserFromUAE() ? appState.getUserRegistrationPayload.dob! : appState.getNHICUserData.dateOfBirth ?? "",
+ controller: authVM!.isUserFromUAE() ? authVM!.dobController : null,
+ isEnable: false,
prefix: null,
isBorderAllowed: false,
isAllowLeadingIcon: true,
isReadOnly: true,
leadingIcon: AppAssets.birthday_cake,
- selectionType: authVM!.isUserFromUAE() ? SelectionTypeEnum.calendar : null,
+ selectionType: null,
).paddingSymmetrical(0.h, 16.h),
],
),
@@ -256,7 +255,7 @@ class _RegisterNew extends State {
icon: AppAssets.cancel,
onPressed: () {
Navigator.of(context).pop();
- authVM!.clearDefaultInputValues();
+ // authVM!.clearDefaultInputValues();
},
backgroundColor: AppColors.secondaryLightRedColor,
borderColor: AppColors.secondaryLightRedColor,
diff --git a/lib/presentation/authentication/saved_login_screen.dart b/lib/presentation/authentication/saved_login_screen.dart
index edfc1e7..d711402 100644
--- a/lib/presentation/authentication/saved_login_screen.dart
+++ b/lib/presentation/authentication/saved_login_screen.dart
@@ -84,7 +84,7 @@ class _SavedLogin extends State {
children: [
// Last login info
- ("${LocaleKeys.lastloginBy.tr()} ${loginType.displayName}").toText14(isBold: true, color: AppColors.greyTextColor),
+ ("${LocaleKeys.lastLoginBy.tr()} ${loginType.displayName}").toText14(isBold: true, color: AppColors.greyTextColor),
(appState.getSelectDeviceByImeiRespModelElement!.createdOn != null
? DateUtil.getFormattedDate(DateUtil.convertStringToDate(appState.getSelectDeviceByImeiRespModelElement!.createdOn!), "d MMMM, y 'at' HH:mm")
: '--')
diff --git a/lib/presentation/book_appointment/book_appointment_page.dart b/lib/presentation/book_appointment/book_appointment_page.dart
new file mode 100644
index 0000000..0f9a325
--- /dev/null
+++ b/lib/presentation/book_appointment/book_appointment_page.dart
@@ -0,0 +1,159 @@
+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_state.dart';
+import 'package:hmg_patient_app_new/core/dependencies.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';
+import 'package:hmg_patient_app_new/features/book_appointments/book_appointments_view_model.dart';
+import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
+import 'package:hmg_patient_app_new/presentation/book_appointment/select_clinic_page.dart';
+import 'package:hmg_patient_app_new/presentation/lab/collapsing_list_view.dart';
+import 'package:hmg_patient_app_new/theme/colors.dart';
+import 'package:hmg_patient_app_new/widgets/custom_tab_bar.dart';
+import 'package:hmg_patient_app_new/widgets/transitions/fade_page.dart';
+import 'package:provider/provider.dart';
+
+class BookAppointmentPage extends StatefulWidget {
+ const BookAppointmentPage({super.key});
+
+ @override
+ State createState() => _BookAppointmentPageState();
+}
+
+class _BookAppointmentPageState extends State {
+ late AppState appState;
+
+ @override
+ Widget build(BuildContext context) {
+ appState = getIt.get();
+ return Scaffold(
+ backgroundColor: AppColors.bgScaffoldColor,
+ body: CollapsingListView(
+ title: LocaleKeys.bookAppo.tr(context: context),
+ child: SingleChildScrollView(
+ child: Consumer(builder: (context, bookAppointmentsVM, child) {
+ return Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ SizedBox(height: 16.h),
+ CustomTabBar(
+ activeTextColor: Color(0xffED1C2B),
+ activeBackgroundColor: Color(0xffED1C2B).withValues(alpha: .1),
+ tabs: [
+ CustomTabBarModel(null, "General".needTranslation),
+ CustomTabBarModel(null, "LiveCare".needTranslation),
+ ],
+ onTabChange: (index) {
+ bookAppointmentsVM.onTabChanged(index);
+ },
+ ).paddingSymmetrical(24.h, 0.h),
+ SizedBox(height: 24.h),
+ getSelectedTabData(bookAppointmentsVM.selectedTabIndex),
+ ],
+ );
+ }),
+ ),
+ ),
+ );
+ }
+
+ Widget getSelectedTabData(int index) {
+ switch (index) {
+ case 0:
+ return Column(
+ children: [
+ Container(
+ decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
+ color: AppColors.whiteColor,
+ borderRadius: 24.h,
+ hasShadow: false,
+ ),
+ child: Padding(
+ padding: EdgeInsets.all(16.h),
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Row(
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ children: [
+ Row(
+ children: [
+ Utils.buildSvgWithAssets(icon: AppAssets.search_by_clinic_icon, width: 40.h, height: 40.h),
+ SizedBox(width: 12.h),
+ Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ "Search By Clinic".needTranslation.toText14(color: AppColors.textColor, weight: FontWeight.w500),
+ "Tap to select clinic".needTranslation.toText12(color: AppColors.primaryRedColor, fontWeight: FontWeight.w500),
+ ],
+ ),
+ ],
+ ),
+ Utils.buildSvgWithAssets(icon: AppAssets.forward_arrow_icon, iconColor: AppColors.textColor, width: 15.h, height: 15.h),
+ ],
+ ).onPress(() {
+ Navigator.of(context).push(
+ FadePage(
+ page: SelectClinicPage(),
+ ),
+ );
+ }),
+ SizedBox(height: 16.h),
+ Divider(color: AppColors.borderOnlyColor.withValues(alpha: 0.1), height: 1.h),
+ SizedBox(height: 16.h),
+ Row(
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ children: [
+ Row(
+ children: [
+ Utils.buildSvgWithAssets(icon: AppAssets.search_by_doctor_icon, width: 40.h, height: 40.h),
+ SizedBox(width: 12.h),
+ Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ "Search By Doctor".needTranslation.toText14(color: AppColors.textColor, weight: FontWeight.w500),
+ "Tap to select".needTranslation.toText12(color: AppColors.primaryRedColor, fontWeight: FontWeight.w500),
+ ],
+ ),
+ ],
+ ),
+ Utils.buildSvgWithAssets(icon: AppAssets.forward_arrow_icon, iconColor: AppColors.textColor, width: 15.h, height: 15.h),
+ ],
+ ).onPress(() {}),
+ SizedBox(height: 16.h),
+ Divider(color: AppColors.borderOnlyColor.withValues(alpha: 0.1), height: 1.h),
+ SizedBox(height: 16.h),
+ Row(
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ children: [
+ Row(
+ children: [
+ Utils.buildSvgWithAssets(icon: AppAssets.search_by_region_icon, width: 40.h, height: 40.h),
+ SizedBox(width: 12.h),
+ Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ "Search By Region".needTranslation.toText14(color: AppColors.textColor, weight: FontWeight.w500),
+ "Central Region".needTranslation.toText12(color: AppColors.primaryRedColor, fontWeight: FontWeight.w500),
+ ],
+ ),
+ ],
+ ),
+ Utils.buildSvgWithAssets(icon: AppAssets.forward_arrow_icon, iconColor: AppColors.textColor, width: 15.h, height: 15.h),
+ ],
+ ).onPress(() {}),
+ ],
+ ),
+ ),
+ ),
+ ],
+ ).paddingSymmetrical(24.h, 0.h);
+ default:
+ SizedBox.shrink();
+ }
+ return Container();
+ }
+}
diff --git a/lib/presentation/book_appointment/select_clinic_page.dart b/lib/presentation/book_appointment/select_clinic_page.dart
new file mode 100644
index 0000000..496f7d5
--- /dev/null
+++ b/lib/presentation/book_appointment/select_clinic_page.dart
@@ -0,0 +1,29 @@
+import 'package:easy_localization/easy_localization.dart';
+import 'package:flutter/material.dart';
+import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
+import 'package:hmg_patient_app_new/presentation/lab/collapsing_list_view.dart';
+import 'package:hmg_patient_app_new/theme/colors.dart';
+
+class SelectClinicPage extends StatefulWidget {
+ const SelectClinicPage({super.key});
+
+ @override
+ State createState() => _SelectClinicPageState();
+}
+
+class _SelectClinicPageState extends State {
+ @override
+ Widget build(BuildContext context) {
+ return Scaffold(
+ backgroundColor: AppColors.bgScaffoldColor,
+ body: CollapsingListView(
+ title: LocaleKeys.selectClinic.tr(context: context),
+ child: SingleChildScrollView(
+ child: Column(
+ children: [],
+ ),
+ ),
+ ),
+ );
+ }
+}
diff --git a/lib/presentation/habib_wallet/habib_wallet_page.dart b/lib/presentation/habib_wallet/habib_wallet_page.dart
new file mode 100644
index 0000000..1d24d05
--- /dev/null
+++ b/lib/presentation/habib_wallet/habib_wallet_page.dart
@@ -0,0 +1,109 @@
+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_state.dart';
+import 'package:hmg_patient_app_new/core/dependencies.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';
+import 'package:hmg_patient_app_new/features/habib_wallet/habib_wallet_view_model.dart';
+import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
+import 'package:hmg_patient_app_new/presentation/habib_wallet/recharge_wallet_page.dart';
+import 'package:hmg_patient_app_new/presentation/lab/collapsing_list_view.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/transitions/fade_page.dart';
+import 'package:provider/provider.dart';
+
+class HabibWalletPage extends StatefulWidget {
+ const HabibWalletPage({super.key});
+
+ @override
+ State createState() => _HabibWalletState();
+}
+
+class _HabibWalletState extends State {
+ @override
+ Widget build(BuildContext context) {
+ AppState _appState = getIt.get();
+ return Scaffold(
+ backgroundColor: AppColors.bgScaffoldColor,
+ body: CollapsingListView(
+ title: LocaleKeys.myWallet.tr(),
+ child: Padding(
+ padding: EdgeInsets.all(24.h),
+ child: SingleChildScrollView(
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Container(
+ width: double.infinity,
+ height: 180.h,
+ decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
+ color: AppColors.blackBgColor,
+ borderRadius: 24,
+ ),
+ child: Padding(
+ padding: EdgeInsets.all(16.h),
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Row(
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ children: [
+ Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ "${_appState.getAuthenticatedUser()!.firstName!} ${_appState.getAuthenticatedUser()!.lastName!}".toText19(isBold: true, color: AppColors.whiteColor),
+ "MRN: ${_appState.getAuthenticatedUser()!.patientId!}".toText14(weight: FontWeight.w500, color: AppColors.greyTextColor),
+ ],
+ ),
+ Utils.buildSvgWithAssets(icon: AppAssets.habiblogo, width: 24.h, height: 24.h),
+ ],
+ ),
+ Spacer(),
+ LocaleKeys.balanceAmount.tr(context: context).toText14(weight: FontWeight.w500, color: AppColors.whiteColor),
+ Consumer(builder: (context, habibWalletVM, child) {
+ return Utils.getPaymentAmountWithSymbol(habibWalletVM.habibWalletAmount.toString().toText32(isBold: true, color: AppColors.whiteColor), AppColors.whiteColor, 13.h,
+ isExpanded: false)
+ .toShimmer2(isShow: habibWalletVM.isWalletAmountLoading, radius: 12.h, width: 80.h, height: 40.h);
+ }),
+ ],
+ ),
+ ),
+ ),
+ SizedBox(height: 16.h),
+ Row(
+ mainAxisAlignment: MainAxisAlignment.center,
+ children: [
+ CustomButton(
+ icon: AppAssets.recharge_icon,
+ iconSize: 21.h,
+ text: "Recharge".needTranslation,
+ onPressed: () {
+ Navigator.of(context).push(
+ FadePage(
+ page: RechargeWalletPage(),
+ ),
+ );
+ },
+ backgroundColor: AppColors.infoColor,
+ borderColor: AppColors.infoColor,
+ textColor: AppColors.whiteColor,
+ fontSize: 14,
+ fontWeight: FontWeight.bold,
+ borderRadius: 12,
+ padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
+ height: 40.h,
+ ),
+ ],
+ ),
+ ],
+ ),
+ ),
+ ),
+ ),
+ );
+ }
+}
diff --git a/lib/presentation/habib_wallet/recharge_wallet_page.dart b/lib/presentation/habib_wallet/recharge_wallet_page.dart
new file mode 100644
index 0000000..ff1a505
--- /dev/null
+++ b/lib/presentation/habib_wallet/recharge_wallet_page.dart
@@ -0,0 +1,229 @@
+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_state.dart';
+import 'package:hmg_patient_app_new/core/dependencies.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';
+import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
+import 'package:hmg_patient_app_new/presentation/lab/collapsing_list_view.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/common_bottom_sheet.dart';
+import 'package:hmg_patient_app_new/widgets/input_widget.dart';
+
+import 'widgets/select-medical_file.dart';
+
+class RechargeWalletPage extends StatefulWidget {
+ const RechargeWalletPage({super.key});
+
+ @override
+ State createState() => _RechargeWalletPageState();
+}
+
+class _RechargeWalletPageState extends State {
+ FocusNode textFocusNode = FocusNode();
+
+ @override
+ Widget build(BuildContext context) {
+ AppState appState = getIt.get();
+ return Scaffold(
+ backgroundColor: AppColors.bgScaffoldColor,
+ body: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Expanded(
+ child: CollapsingListView(
+ title: LocaleKeys.createAdvancedPayment.tr(context: context),
+ child: SingleChildScrollView(
+ child: Padding(
+ padding: EdgeInsets.all(24.h),
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Container(
+ height: 135.h,
+ decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
+ color: AppColors.whiteColor,
+ borderRadius: 24.h,
+ hasShadow: false,
+ side: BorderSide(color: AppColors.textColor, width: 2.h),
+ ),
+ child: Padding(
+ padding: EdgeInsets.all(16.h),
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ "Enter an amount".needTranslation.toText14(color: AppColors.greyTextColor, weight: FontWeight.w500),
+ Spacer(),
+ Row(
+ crossAxisAlignment: CrossAxisAlignment.end,
+ children: [
+ Utils.getPaymentAmountWithSymbol(
+ SizedBox(
+ width: 150.h,
+ child: TextInputWidget(
+ labelText: "",
+ hintText: "",
+ isEnable: true,
+ prefix: null,
+ isAllowRadius: true,
+ isBorderAllowed: false,
+ isAllowLeadingIcon: true,
+ autoFocus: true,
+ fontSize: 40,
+ padding: EdgeInsets.symmetric(horizontal: 8.h, vertical: 0.h),
+ focusNode: textFocusNode,
+ isWalletAmountInput: true,
+ // leadingIcon: AppAssets.student_card,
+ ),
+ ),
+ AppColors.textColor,
+ 13.h,
+ isExpanded: false),
+ const Spacer(),
+ "SAR".needTranslation.toText20(color: AppColors.greyTextColor, weight: FontWeight.w500),
+ ],
+ ),
+ ],
+ ),
+ ),
+ ),
+ SizedBox(height: 24.h),
+ Container(
+ decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
+ color: AppColors.whiteColor,
+ borderRadius: 24.h,
+ hasShadow: false,
+ ),
+ child: Padding(
+ padding: EdgeInsets.all(16.h),
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Row(
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ children: [
+ Row(
+ children: [
+ Utils.buildSvgWithAssets(icon: AppAssets.my_account_icon, width: 40.h, height: 40.h),
+ SizedBox(width: 8.h),
+ Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ LocaleKeys.myAccount.tr(context: context).toText16(color: AppColors.textColor, weight: FontWeight.w500),
+ "${LocaleKeys.medicalFile.tr(context: context)}: ${appState.getAuthenticatedUser()!.patientId}"
+ .toText14(color: AppColors.greyTextColor, weight: FontWeight.w500),
+ ],
+ ),
+ ],
+ ),
+ Utils.buildSvgWithAssets(icon: AppAssets.arrow_down, width: 25.h, height: 25.h),
+ ],
+ ).onPress(() {
+ // showCommonBottomSheetWithoutHeight(context, title: "Select Medical File".needTranslation, child: SelectMedicalFile(), callBackFunc: () {}, isFullScreen: false);
+ showCommonBottomSheetWithoutHeight(context, title: "Select Medical File".needTranslation, child: const MultiPageBottomSheet(), callBackFunc: () {}, isFullScreen: false);
+ }),
+ SizedBox(height: 16.h),
+ Divider(color: AppColors.borderOnlyColor.withValues(alpha: 0.1), height: 1.h),
+ SizedBox(height: 16.h),
+ Row(
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ children: [
+ Row(
+ children: [
+ Utils.buildSvgWithAssets(icon: AppAssets.select_hospital_icon, width: 40.h, height: 40.h),
+ SizedBox(width: 8.h),
+ Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ LocaleKeys.hospital.tr(context: context).toText16(color: AppColors.textColor, weight: FontWeight.w500),
+ "Olaya".toText14(color: AppColors.greyTextColor, weight: FontWeight.w500),
+ ],
+ ),
+ ],
+ ),
+ Utils.buildSvgWithAssets(icon: AppAssets.arrow_down, width: 25.h, height: 25.h),
+ ],
+ ),
+ SizedBox(height: 16.h),
+ Divider(color: AppColors.borderOnlyColor.withValues(alpha: 0.1), height: 1.h),
+ SizedBox(height: 16.h),
+ Row(
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ children: [
+ Row(
+ children: [
+ Utils.buildSvgWithAssets(icon: AppAssets.email_icon, width: 40.h, height: 40.h),
+ SizedBox(width: 8.h),
+ Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ LocaleKeys.email.tr(context: context).toText12(color: AppColors.greyTextColor, fontWeight: FontWeight.w500),
+ "${appState.getAuthenticatedUser()!.emailAddress}".toText16(color: AppColors.textColor, weight: FontWeight.w500),
+ ],
+ ),
+ ],
+ ),
+ ],
+ ),
+ SizedBox(height: 16.h),
+ Divider(color: AppColors.borderOnlyColor.withValues(alpha: 0.1), height: 1.h),
+ SizedBox(height: 16.h),
+ Row(
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ children: [
+ Row(
+ children: [
+ Utils.buildSvgWithAssets(icon: AppAssets.notes_icon, width: 40.h, height: 40.h),
+ SizedBox(width: 8.h),
+ Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ LocaleKeys.notes.tr(context: context).toText12(color: AppColors.greyTextColor, fontWeight: FontWeight.w500),
+ "Lorem Ipsum".toText16(color: AppColors.textColor, weight: FontWeight.w500),
+ ],
+ ),
+ ],
+ ),
+ ],
+ ),
+ SizedBox(height: 8.h),
+ ],
+ ),
+ ),
+ ),
+ ],
+ ),
+ ),
+ ),
+ )),
+ Container(
+ decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
+ color: AppColors.whiteColor,
+ borderRadius: 24.h,
+ hasShadow: false,
+ ),
+ child: CustomButton(
+ text: LocaleKeys.next.tr(context: context),
+ onPressed: () {},
+ backgroundColor: AppColors.primaryRedColor,
+ borderColor: AppColors.primaryRedColor,
+ textColor: AppColors.whiteColor,
+ fontSize: 16,
+ fontWeight: FontWeight.w500,
+ borderRadius: 12,
+ padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
+ height: 50.h,
+ icon: AppAssets.appointment_pay_icon,
+ iconColor: AppColors.whiteColor,
+ iconSize: 18.h,
+ ).paddingSymmetrical(24.h, 24.h),
+ ),
+ ],
+ ),
+ );
+ }
+}
diff --git a/lib/presentation/habib_wallet/widgets/select-medical_file.dart b/lib/presentation/habib_wallet/widgets/select-medical_file.dart
new file mode 100644
index 0000000..a70edb3
--- /dev/null
+++ b/lib/presentation/habib_wallet/widgets/select-medical_file.dart
@@ -0,0 +1,238 @@
+// import 'package:flutter/cupertino.dart';
+// import 'package:hmg_patient_app_new/core/utils/size_utils.dart';
+//
+// class SelectMedicalFile extends StatelessWidget {
+// const SelectMedicalFile({super.key});
+//
+// @override
+// Widget build(BuildContext context) {
+// return Padding(
+// padding: EdgeInsets.all(24.h),
+// child: Column(
+// crossAxisAlignment: CrossAxisAlignment.start,
+// children: [
+// Container()
+// ],
+// ),
+// );
+// }
+// }
+
+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_state.dart';
+import 'package:hmg_patient_app_new/core/dependencies.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';
+import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
+import 'package:hmg_patient_app_new/theme/colors.dart';
+
+class MultiPageBottomSheet extends StatefulWidget {
+ const MultiPageBottomSheet({Key? key}) : super(key: key);
+
+ @override
+ State createState() => _MultiPageBottomSheetState();
+}
+
+class _MultiPageBottomSheetState extends State {
+ final PageController _pageController = PageController();
+ int _currentPage = 0;
+ final int _totalPages = 3;
+
+ late AppState appState;
+
+ @override
+ void dispose() {
+ _pageController.dispose();
+ super.dispose();
+ }
+
+ void _nextPage() {
+ if (_currentPage < _totalPages - 1) {
+ _pageController.animateToPage(
+ _currentPage + 2,
+ duration: const Duration(milliseconds: 300),
+ curve: Curves.easeInOut,
+ );
+ }
+ }
+
+ void _previousPage() {
+ if (_currentPage > 0) {
+ _pageController.previousPage(
+ duration: const Duration(milliseconds: 300),
+ curve: Curves.easeInOut,
+ );
+ }
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ appState = getIt.get();
+ return Container(
+ height: MediaQuery.of(context).size.height * 0.38,
+ child: Column(
+ children: [
+ SizedBox(height: 12.h),
+ Expanded(
+ child: PageView(
+ controller: _pageController,
+ onPageChanged: (index) {
+ setState(() {
+ _currentPage = index;
+ });
+ },
+ children: [
+ _buildPage1(),
+ _buildPage2(),
+ _buildPage3(),
+ ],
+ ),
+ ),
+ ],
+ ),
+ );
+ }
+
+ Widget _buildPage1() {
+ return Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Container(
+ decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
+ color: AppColors.whiteColor,
+ borderRadius: 16.h,
+ hasShadow: false,
+ ),
+ child: Row(
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ children: [
+ Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ LocaleKeys.myMedicalFile.tr(context: context).toText16(color: AppColors.textColor, weight: FontWeight.w500),
+ "${LocaleKeys.fileno.tr(context: context)}: ${appState.getAuthenticatedUser()!.patientId}".toText12(color: AppColors.greyTextColor, fontWeight: FontWeight.w500),
+ ],
+ ),
+ Utils.buildSvgWithAssets(icon: AppAssets.forward_chevron_icon, iconColor: AppColors.textColor, width: 15.h, height: 15.h),
+ ],
+ ).paddingAll(16.h),
+ ).onPress(() {
+ Navigator.of(context).pop();
+ }),
+ SizedBox(height: 16.h),
+ Container(
+ decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
+ color: AppColors.whiteColor,
+ borderRadius: 16.h,
+ hasShadow: false,
+ ),
+ child: Row(
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ children: [
+ Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ LocaleKeys.familyTitle.tr(context: context).toText16(color: AppColors.textColor, weight: FontWeight.w500),
+ "Select a medical file from your family".needTranslation.toText14(color: AppColors.greyTextColor, weight: FontWeight.w500),
+ ],
+ ),
+ Utils.buildSvgWithAssets(icon: AppAssets.forward_chevron_icon, iconColor: AppColors.textColor, width: 15.h, height: 15.h),
+ ],
+ ).paddingAll(16.h),
+ ),
+ SizedBox(height: 16.h),
+ Container(
+ decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
+ color: AppColors.whiteColor,
+ borderRadius: 16.h,
+ hasShadow: false,
+ ),
+ child: Row(
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ children: [
+ Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ LocaleKeys.otherAccount.tr(context: context).toText16(color: AppColors.textColor, weight: FontWeight.w500),
+ "Any active medical file from HMG".toText14(color: AppColors.greyTextColor, weight: FontWeight.w500),
+ ],
+ ),
+ Utils.buildSvgWithAssets(icon: AppAssets.forward_chevron_icon, iconColor: AppColors.textColor, width: 15.h, height: 15.h),
+ ],
+ ).paddingAll(16.h),
+ ).onPress(() {
+ _pageController.animateToPage(
+ 2,
+ duration: const Duration(milliseconds: 300),
+ curve: Curves.easeInOut,
+ );
+ }),
+ ],
+ );
+ }
+
+ Widget _buildPage2() {
+ return Padding(
+ padding: const EdgeInsets.all(16.0),
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Text(
+ 'Page 2: Settings',
+ style: Theme.of(context).textTheme.headlineSmall,
+ ),
+ const SizedBox(height: 16),
+ SwitchListTile(
+ title: const Text('Enable notifications'),
+ value: true,
+ onChanged: (value) {},
+ ),
+ SwitchListTile(
+ title: const Text('Dark mode'),
+ value: false,
+ onChanged: (value) {},
+ ),
+ const ListTile(
+ leading: Icon(Icons.language),
+ title: Text('Language'),
+ subtitle: Text('English'),
+ trailing: Icon(Icons.arrow_forward_ios),
+ ),
+ ],
+ ),
+ );
+ }
+
+ Widget _buildPage3() {
+ return Padding(
+ padding: const EdgeInsets.all(16.0),
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Text(
+ 'Page 3: Summary',
+ style: Theme.of(context).textTheme.headlineSmall,
+ ),
+ const SizedBox(height: 16),
+ const Card(
+ child: Padding(
+ padding: EdgeInsets.all(16.0),
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Text('Configuration Complete!'),
+ SizedBox(height: 8),
+ Text('Your settings have been saved successfully.'),
+ ],
+ ),
+ ),
+ ),
+ ],
+ ),
+ );
+ }
+}
diff --git a/lib/presentation/home/landing_page.dart b/lib/presentation/home/landing_page.dart
index 58aff04..26e5147 100644
--- a/lib/presentation/home/landing_page.dart
+++ b/lib/presentation/home/landing_page.dart
@@ -1,3 +1,5 @@
+import 'dart:async';
+
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:flutter_staggered_animations/flutter_staggered_animations.dart';
@@ -10,6 +12,9 @@ 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/authentication/authentication_view_model.dart';
+import 'package:hmg_patient_app_new/features/habib_wallet/habib_wallet_view_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';
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
import 'package:hmg_patient_app_new/presentation/authentication/quick_login.dart';
import 'package:hmg_patient_app_new/presentation/home/data/landing_page_data.dart';
@@ -37,23 +42,41 @@ class LandingPage extends StatefulWidget {
class _LandingPageState extends State {
late final AuthenticationViewModel authVM;
bool isDone = false;
+ late final HabibWalletViewModel habibWalletVM;
+
+ late AppState appState;
+ late MyAppointmentsViewModel myAppointmentsViewModel;
+ late PrescriptionsViewModel prescriptionsViewModel;
+
@override
void initState() {
authVM = context.read();
+ habibWalletVM = context.read();
authVM.savePushTokenToAppState();
if (mounted) {
authVM.checkLastLoginStatus(() {
- showQuickLogin(context);
+ showQuickLogin(context);
});
}
+ scheduleMicrotask(() {
+ if (appState.isAuthenticated) {
+ habibWalletVM.initHabibWalletProvider();
+ habibWalletVM.getPatientBalanceAmount();
+ myAppointmentsViewModel.initAppointmentsViewModel();
+ myAppointmentsViewModel.getPatientAppointments(true, false);
+ myAppointmentsViewModel.getPatientMyDoctors();
+ prescriptionsViewModel.initPrescriptionsViewModel();
+ }
+ });
super.initState();
}
@override
Widget build(BuildContext context) {
- AppState appState = getIt.get();
+ appState = getIt.get();
NavigationService navigationService = getIt.get();
-
+ myAppointmentsViewModel = Provider.of(context, listen: false);
+ prescriptionsViewModel = Provider.of(context, listen: false);
return Scaffold(
backgroundColor: AppColors.bgScaffoldColor,
body: SingleChildScrollView(
@@ -324,29 +347,22 @@ class _LandingPageState extends State {
void showQuickLogin(BuildContext context) {
showCommonBottomSheetWithoutHeight(
-
context,
title: "",
isCloseButtonVisible: false,
- child:
- StatefulBuilder(
- builder: (context, setState) {
- return QuickLogin(
- isDone: isDone,
- onPressed: () {
- // sharedPref.setBool(HAS_ENABLED_QUICK_LOGIN, true);
- authVM.loginWithFingerPrintFace((){
-
- isDone = true;
- setState(() {
-
+ child: StatefulBuilder(builder: (context, setState) {
+ return QuickLogin(
+ isDone: isDone,
+ onPressed: () {
+ // sharedPref.setBool(HAS_ENABLED_QUICK_LOGIN, true);
+ authVM.loginWithFingerPrintFace(() {
+ isDone = true;
+ setState(() {});
});
- });
-
- },
- );
+ },
+ );
}),
- // height: isDone == false ? ResponsiveExtension.screenHeight * 0.5 : ResponsiveExtension.screenHeight * 0.3,
+ // height: isDone == false ? ResponsiveExtension.screenHeight * 0.5 : ResponsiveExtension.screenHeight * 0.3,
isFullScreen: false,
callBackFunc: () {
isDone = true;
diff --git a/lib/presentation/home/navigation_screen.dart b/lib/presentation/home/navigation_screen.dart
index 152bbd2..bdce393 100644
--- a/lib/presentation/home/navigation_screen.dart
+++ b/lib/presentation/home/navigation_screen.dart
@@ -1,4 +1,5 @@
import 'package:flutter/material.dart';
+import 'package:hmg_patient_app_new/presentation/book_appointment/book_appointment_page.dart';
import 'package:hmg_patient_app_new/presentation/home/landing_page.dart';
import 'package:hmg_patient_app_new/presentation/medical_file/medical_file_page.dart';
import 'package:hmg_patient_app_new/widgets/bottom_navigation/bottom_navigation.dart';
@@ -23,7 +24,7 @@ class _LandingNavigationState extends State {
children: [
const LandingPage(),
MedicalFilePage(),
- const LandingPage(),
+ const BookAppointmentPage(),
const LandingPage(),
const LandingPage(),
],
diff --git a/lib/presentation/home/widgets/habib_wallet_card.dart b/lib/presentation/home/widgets/habib_wallet_card.dart
index 80855dd..3509000 100644
--- a/lib/presentation/home/widgets/habib_wallet_card.dart
+++ b/lib/presentation/home/widgets/habib_wallet_card.dart
@@ -4,8 +4,12 @@ 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';
+import 'package:hmg_patient_app_new/features/habib_wallet/habib_wallet_view_model.dart';
+import 'package:hmg_patient_app_new/presentation/habib_wallet/habib_wallet_page.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/transitions/fade_page.dart';
+import 'package:provider/provider.dart';
class HabibWalletCard extends StatelessWidget {
const HabibWalletCard({super.key});
@@ -69,19 +73,21 @@ class HabibWalletCard extends StatelessWidget {
],
),
SizedBox(height: 4.h),
- Row(
- children: [
- Utils.buildSvgWithAssets(
- icon: AppAssets.saudi_riyal_icon,
- iconColor: AppColors.dividerColor,
- width: 24.h,
- height: 24.h,
- fit: BoxFit.contain,
- ),
- SizedBox(width: 8.h),
- "200.18".toText32(isBold: true),
- ],
- ),
+ Consumer(builder: (context, habibWalletVM, child) {
+ return Row(
+ children: [
+ Utils.buildSvgWithAssets(
+ icon: AppAssets.saudi_riyal_icon,
+ iconColor: AppColors.dividerColor,
+ width: 24.h,
+ height: 24.h,
+ fit: BoxFit.contain,
+ ),
+ SizedBox(width: 8.h),
+ habibWalletVM.habibWalletAmount.toString().toText32(isBold: true).toShimmer2(isShow: habibWalletVM.isWalletAmountLoading, radius: 12.h, width: 80.h, height: 40.h),
+ ],
+ );
+ }),
Padding(
padding: EdgeInsets.symmetric(horizontal: 50.h),
child: Row(
@@ -90,7 +96,13 @@ class HabibWalletCard extends StatelessWidget {
SizedBox(width: 2.h),
Icon(Icons.arrow_forward_ios, color: AppColors.primaryRedColor, size: 10.h),
],
- ),
+ ).onPress(() {
+ Navigator.of(context).push(
+ FadePage(
+ page: HabibWalletPage(),
+ ),
+ );
+ }),
),
SizedBox(height: 16.h),
Row(
@@ -103,7 +115,7 @@ class HabibWalletCard extends StatelessWidget {
CustomButton(
icon: AppAssets.recharge_icon,
iconSize: 18.h,
- text: "Recharge",
+ text: "Recharge".needTranslation,
onPressed: () {},
backgroundColor: AppColors.infoColor,
borderColor: AppColors.infoColor,
diff --git a/lib/presentation/home/widgets/small_service_card.dart b/lib/presentation/home/widgets/small_service_card.dart
index f988e18..6e1c588 100644
--- a/lib/presentation/home/widgets/small_service_card.dart
+++ b/lib/presentation/home/widgets/small_service_card.dart
@@ -2,8 +2,10 @@ import 'package:flutter/material.dart';
import 'package:hmg_patient_app_new/core/utils/size_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/presentation/appointments/my_doctors_page.dart';
import 'package:hmg_patient_app_new/presentation/insurance/insurance_home_page.dart';
import 'package:hmg_patient_app_new/presentation/lab/lab_orders_page.dart';
+import 'package:hmg_patient_app_new/presentation/medical_file/patient_sickleaves_list_page.dart';
import 'package:hmg_patient_app_new/presentation/prescriptions/prescriptions_list_page.dart';
import 'package:hmg_patient_app_new/widgets/transitions/fade_page.dart';
@@ -85,6 +87,22 @@ class SmallServiceCard extends StatelessWidget {
),
);
break;
+
+ case "my_doctors":
+ Navigator.of(context).push(
+ FadePage(
+ page: MyDoctorsPage(),
+ ),
+ );
+ break;
+
+ case "sick_leaves":
+ Navigator.of(context).push(
+ FadePage(
+ page: PatientSickleavesListPage(),
+ ),
+ );
+ break;
default:
// Handle unknown service
break;
diff --git a/lib/presentation/insurance/insurance_home_page.dart b/lib/presentation/insurance/insurance_home_page.dart
index 451eeee..dd63e55 100644
--- a/lib/presentation/insurance/insurance_home_page.dart
+++ b/lib/presentation/insurance/insurance_home_page.dart
@@ -9,6 +9,7 @@ import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
import 'package:hmg_patient_app_new/features/insurance/insurance_view_model.dart';
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
import 'package:hmg_patient_app_new/presentation/insurance/widgets/patient_insurance_card.dart';
+import 'package:hmg_patient_app_new/presentation/lab/collapsing_list_view.dart';
import 'package:hmg_patient_app_new/presentation/lab/search_lab_report.dart';
import 'package:hmg_patient_app_new/theme/colors.dart';
import 'package:hmg_patient_app_new/extensions/widget_extensions.dart';
@@ -39,52 +40,56 @@ class _InsuranceHomePageState extends State {
@override
Widget build(BuildContext context) {
- insuranceViewModel = Provider.of(context);
+ insuranceViewModel = Provider.of(context, listen: false);
return Scaffold(
backgroundColor: AppColors.bgScaffoldColor,
- appBar: AppBar(
- title: LocaleKeys.insurance.tr(context: context).toText18(),
- backgroundColor: AppColors.bgScaffoldColor,
- ),
- body: SingleChildScrollView(
- child: Consumer(builder: (context, insuranceVM, child) {
- return Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- Row(
- mainAxisAlignment: MainAxisAlignment.spaceBetween,
- children: [
- "${LocaleKeys.insurance.tr(context: context)} ${LocaleKeys.updateInsurance.tr(context: context)}".toText24(isBold: true),
- CustomButton(
- icon: AppAssets.insurance_history_icon,
- iconColor: AppColors.primaryRedColor,
- iconSize: 21.h,
- text: LocaleKeys.history.tr(context: context),
- onPressed: () {
- insuranceVM.setIsInsuranceHistoryLoading(true);
- insuranceVM.getPatientInsuranceCardHistory();
- showCommonBottomSheet(context,
- child: InsuranceHistory(), callBackFunc: (str){}, title: "", height: ResponsiveExtension.screenHeight * 0.65, isCloseButtonVisible: false, isFullScreen: false);
- },
- backgroundColor: AppColors.primaryRedColor.withOpacity(0.1),
- borderColor: AppColors.primaryRedColor.withOpacity(0.0),
- textColor: AppColors.primaryRedColor,
- fontSize: 14,
- fontWeight: FontWeight.w600,
- borderRadius: 12,
- padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
- height: 40.h,
- ),
- ],
- ).paddingSymmetrical(24.h, 24.h),
- insuranceVM.isInsuranceLoading
- ? const MoviesShimmerWidget().paddingSymmetrical(24.h, 0)
- : PatientInsuranceCard(
- insuranceCardDetailsModel: insuranceVM.patientInsuranceList.first,
- isInsuranceExpired: DateTime.now().isAfter(DateUtil.convertStringToDate(insuranceVM.patientInsuranceList.first.cardValidTo))),
- ],
- );
- }),
+ body: CollapsingListView(
+ title: "${LocaleKeys.insurance.tr(context: context)} ${LocaleKeys.updateInsurance.tr(context: context)}",
+ history: () {
+ insuranceViewModel.setIsInsuranceHistoryLoading(true);
+ insuranceViewModel.getPatientInsuranceCardHistory();
+ showCommonBottomSheet(context,
+ child: InsuranceHistory(), callBackFunc: (str) {}, title: "", height: ResponsiveExtension.screenHeight * 0.65, isCloseButtonVisible: false, isFullScreen: false);
+ },
+ child: SingleChildScrollView(
+ child: Consumer(builder: (context, insuranceVM, child) {
+ return Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ // Row(
+ // mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ // children: [
+ // "${LocaleKeys.insurance.tr(context: context)} ${LocaleKeys.updateInsurance.tr(context: context)}".toText24(isBold: true),
+ // CustomButton(
+ // icon: AppAssets.insurance_history_icon,
+ // iconColor: AppColors.primaryRedColor,
+ // iconSize: 21.h,
+ // text: LocaleKeys.history.tr(context: context),
+ // onPressed: () {
+ // },
+ // backgroundColor: AppColors.primaryRedColor.withOpacity(0.1),
+ // borderColor: AppColors.primaryRedColor.withOpacity(0.0),
+ // textColor: AppColors.primaryRedColor,
+ // fontSize: 14,
+ // fontWeight: FontWeight.w600,
+ // borderRadius: 12,
+ // padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
+ // height: 40.h,
+ // ),
+ // ],
+ // ).paddingSymmetrical(24.h, 24.h),
+ insuranceVM.isInsuranceLoading
+ ? const MoviesShimmerWidget().paddingSymmetrical(24.h, 0)
+ : Padding(
+ padding: EdgeInsets.only(top: 24.h),
+ child: PatientInsuranceCard(
+ insuranceCardDetailsModel: insuranceVM.patientInsuranceList.first,
+ isInsuranceExpired: DateTime.now().isAfter(DateUtil.convertStringToDate(insuranceVM.patientInsuranceList.first.cardValidTo))),
+ ),
+ ],
+ );
+ }),
+ ),
),
);
}
diff --git a/lib/presentation/insurance/widgets/insurance_update_details_card.dart b/lib/presentation/insurance/widgets/insurance_update_details_card.dart
index b6a38b2..aa04d8c 100644
--- a/lib/presentation/insurance/widgets/insurance_update_details_card.dart
+++ b/lib/presentation/insurance/widgets/insurance_update_details_card.dart
@@ -69,7 +69,7 @@ class PatientInsuranceCardUpdateCard extends StatelessWidget {
Wrap(
direction: Axis.horizontal,
spacing: 4.h,
- runSpacing: -8.h,
+ runSpacing: 4.h,
children: [
AppCustomChipWidget(
icon: AppAssets.doctor_calendar_icon,
diff --git a/lib/presentation/insurance/widgets/patient_insurance_card.dart b/lib/presentation/insurance/widgets/patient_insurance_card.dart
index 720c452..cf8b7d7 100644
--- a/lib/presentation/insurance/widgets/patient_insurance_card.dart
+++ b/lib/presentation/insurance/widgets/patient_insurance_card.dart
@@ -75,7 +75,7 @@ class PatientInsuranceCard extends StatelessWidget {
Wrap(
direction: Axis.horizontal,
spacing: 4.h,
- runSpacing: -8.h,
+ runSpacing: 4.h,
children: [
AppCustomChipWidget(
icon: AppAssets.doctor_calendar_icon,
diff --git a/lib/presentation/lab/collapsing_list_view.dart b/lib/presentation/lab/collapsing_list_view.dart
index c7f1540..f84872d 100644
--- a/lib/presentation/lab/collapsing_list_view.dart
+++ b/lib/presentation/lab/collapsing_list_view.dart
@@ -21,8 +21,9 @@ class CollapsingListView extends StatelessWidget {
VoidCallback? history;
Widget? bottomChild;
bool isClose;
+ bool isLeading;
- CollapsingListView({required this.title, this.child, this.search, this.isClose = false, this.bottomChild, this.report, this.logout, this.history});
+ CollapsingListView({required this.title, this.child, this.search, this.isClose = false, this.bottomChild, this.report, this.logout, this.history, this.isLeading = true});
@override
Widget build(BuildContext context) {
@@ -33,17 +34,18 @@ class CollapsingListView extends StatelessWidget {
CustomScrollView(
slivers: [
SliverAppBar(
+ automaticallyImplyLeading: false,
pinned: true,
expandedHeight: 100,
stretch: true,
systemOverlayStyle: SystemUiOverlayStyle(statusBarBrightness: Brightness.light),
surfaceTintColor: Colors.transparent,
backgroundColor: AppColors.bgScaffoldColor,
- leading: IconButton(
+ leading: isLeading ? IconButton(
icon: Utils.buildSvgWithAssets(icon: isClose ? AppAssets.closeBottomNav : AppAssets.arrow_back, width: 32.h, height: 32.h),
padding: EdgeInsets.only(left: 12),
onPressed: () => Navigator.pop(context),
- ),
+ ) : SizedBox.shrink(),
flexibleSpace: LayoutBuilder(
builder: (context, constraints) {
final double maxHeight = 100;
diff --git a/lib/presentation/lab/lab_orders_page.dart b/lib/presentation/lab/lab_orders_page.dart
index 2c6a131..520bfec 100644
--- a/lib/presentation/lab/lab_orders_page.dart
+++ b/lib/presentation/lab/lab_orders_page.dart
@@ -5,6 +5,7 @@ import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_staggered_animations/flutter_staggered_animations.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/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';
@@ -57,7 +58,7 @@ class _LabOrdersPageState extends State {
}
},
child: SingleChildScrollView(
- padding: EdgeInsets.all(24),
+ padding: EdgeInsets.all(24.h),
physics: NeverScrollableScrollPhysics(),
child: Consumer(
builder: (context, model, child) {
diff --git a/lib/presentation/medical_file/medical_file_page.dart b/lib/presentation/medical_file/medical_file_page.dart
index 47951c4..48193e8 100644
--- a/lib/presentation/medical_file/medical_file_page.dart
+++ b/lib/presentation/medical_file/medical_file_page.dart
@@ -2,27 +2,46 @@ import 'dart:async';
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_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/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';
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/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';
+import 'package:hmg_patient_app_new/features/prescriptions/prescriptions_view_model.dart';
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
import 'package:hmg_patient_app_new/presentation/appointments/my_appointments_page.dart';
+import 'package:hmg_patient_app_new/presentation/appointments/my_doctors_page.dart';
+import 'package:hmg_patient_app_new/presentation/insurance/insurance_home_page.dart';
import 'package:hmg_patient_app_new/presentation/insurance/widgets/patient_insurance_card.dart';
+import 'package:hmg_patient_app_new/presentation/lab/collapsing_list_view.dart';
+import 'package:hmg_patient_app_new/presentation/medical_file/medical_reports_page.dart';
+import 'package:hmg_patient_app_new/presentation/medical_file/patient_sickleaves_list_page.dart';
+import 'package:hmg_patient_app_new/presentation/medical_file/vaccine_list_page.dart';
+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/prescriptions/prescriptions_list_page.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/custom_tab_bar.dart';
import 'package:hmg_patient_app_new/widgets/input_widget.dart';
import 'package:hmg_patient_app_new/widgets/shimmer/movies_shimmer_widget.dart';
import 'package:hmg_patient_app_new/widgets/transitions/fade_page.dart';
import 'package:provider/provider.dart';
+import '../prescriptions/prescription_detail_page.dart';
+import 'widgets/medical_file_appointment_card.dart';
+
class MedicalFilePage extends StatefulWidget {
MedicalFilePage({super.key});
@@ -33,6 +52,8 @@ class MedicalFilePage extends StatefulWidget {
class _MedicalFilePageState extends State {
late InsuranceViewModel insuranceViewModel;
late AppState appState;
+ late MyAppointmentsViewModel myAppointmentsViewModel;
+ late MedicalFileViewModel medicalFileViewModel;
int currentIndex = 0;
@@ -40,180 +61,183 @@ class _MedicalFilePageState extends State {
void initState() {
scheduleMicrotask(() {
insuranceViewModel.initInsuranceProvider();
+ medicalFileViewModel.setIsPatientSickLeaveListLoading(true);
+ medicalFileViewModel.getPatientSickLeaveList();
});
super.initState();
}
@override
Widget build(BuildContext context) {
- insuranceViewModel = Provider.of(context);
+ insuranceViewModel = Provider.of(context, listen: false);
+ myAppointmentsViewModel = Provider.of(context, listen: false);
+ medicalFileViewModel = Provider.of(context, listen: false);
appState = getIt.get();
return Scaffold(
backgroundColor: AppColors.bgScaffoldColor,
- appBar: AppBar(
- title: const Text('Appointments'),
- backgroundColor: AppColors.bgScaffoldColor,
- ),
- body: SingleChildScrollView(
- child: Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- LocaleKeys.medicalFile.tr(context: context).toText22(isBold: true).paddingSymmetrical(24.h, 0.0),
- SizedBox(height: 16.h),
- TextInputWidget(
- labelText: LocaleKeys.search.tr(context: context),
- hintText: "Type any record",
- 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(
+ 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",
+ 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(
+ 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),
+ Row(
+ children: [
+ CustomButton(
+ icon: AppAssets.file_icon,
+ iconColor: AppColors.blackColor,
+ iconSize: 12.h,
+ text: "File no: ${appState.getAuthenticatedUser()!.patientId}",
+ onPressed: () {},
+ backgroundColor: AppColors.greyColor,
+ borderColor: AppColors.greyColor,
+ textColor: AppColors.blackColor,
+ fontSize: 10,
+ fontWeight: FontWeight.normal,
+ borderRadius: 12,
+ padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
+ height: 30.h,
+ ),
+ SizedBox(width: 4.h),
+ CustomButton(
+ text: LocaleKeys.verified.tr(context: context),
+ onPressed: () {},
+ backgroundColor: AppColors.greyColor,
+ borderColor: AppColors.greyColor,
+ textColor: AppColors.blackColor,
+ fontSize: 10,
+ fontWeight: FontWeight.normal,
+ borderRadius: 12,
+ padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
+ height: 30.h,
+ ),
+ ],
+ ),
+ ],
+ )
+ ],
+ ),
+ SizedBox(height: 16.h),
+ Divider(color: AppColors.dividerColor, height: 1.h),
+ SizedBox(height: 16.h),
+ Row(
+ children: [
+ CustomButton(
+ text: "${appState.getAuthenticatedUser()!.age} Years Old",
+ onPressed: () {},
+ backgroundColor: AppColors.greyColor,
+ borderColor: AppColors.greyColor,
+ textColor: AppColors.blackColor,
+ fontSize: 10,
+ fontWeight: FontWeight.normal,
+ borderRadius: 12,
+ padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
+ height: 30.h,
+ ),
+ SizedBox(width: 4.h),
+ CustomButton(
+ icon: AppAssets.blood_icon,
+ iconColor: AppColors.primaryRedColor,
+ iconSize: 13.h,
+ text: "Blood: ${appState.getUserBloodGroup}",
+ onPressed: () {},
+ backgroundColor: AppColors.greyColor,
+ borderColor: AppColors.greyColor,
+ textColor: AppColors.blackColor,
+ fontSize: 10,
+ fontWeight: FontWeight.normal,
+ borderRadius: 12,
+ padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
+ height: 30.h,
+ ),
+ // SizedBox(width: 4.h),
+ // CustomButton(
+ // icon: AppAssets.insurance_active_icon,
+ // iconColor: AppColors.successColor,
+ // iconSize: 13.h,
+ // text: "Insurance Active",
+ // onPressed: () {},
+ // backgroundColor: AppColors.bgGreenColor.withOpacity(0.20),
+ // borderColor: AppColors.bgGreenColor.withOpacity(0.0),
+ // textColor: AppColors.blackColor,
+ // fontSize: 10,
+ // fontWeight: FontWeight.normal,
+ // borderRadius: 12,
+ // padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
+ // height: 30.h,
+ // ),
+ ],
+ ),
+ SizedBox(height: 8.h),
+ ],
+ ),
+ ),
+ ).paddingSymmetrical(24.h, 0.0),
+ SizedBox(height: 16.h),
+ Consumer(builder: (context, medicalFileVM, child) {
+ return Column(
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),
- Row(
- children: [
- CustomButton(
- icon: AppAssets.file_icon,
- iconColor: AppColors.blackColor,
- iconSize: 12.h,
- text: "File no: ${appState.getAuthenticatedUser()!.patientId}",
- onPressed: () {},
- backgroundColor: AppColors.greyColor,
- borderColor: AppColors.greyColor,
- textColor: AppColors.blackColor,
- fontSize: 10,
- fontWeight: FontWeight.normal,
- borderRadius: 12,
- padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
- height: 30.h,
- ),
- SizedBox(width: 4.h),
- CustomButton(
- text: LocaleKeys.verified.tr(context: context),
- onPressed: () {},
- backgroundColor: AppColors.greyColor,
- borderColor: AppColors.greyColor,
- textColor: AppColors.blackColor,
- fontSize: 10,
- fontWeight: FontWeight.normal,
- borderRadius: 12,
- padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
- height: 30.h,
- ),
- ],
- ),
- ],
- )
- ],
- ),
- SizedBox(height: 16.h),
- Divider(color: AppColors.dividerColor, height: 1.h),
- SizedBox(height: 16.h),
- Row(
- children: [
- CustomButton(
- text: "${appState.getAuthenticatedUser()!.age} Years Old",
- onPressed: () {},
- backgroundColor: AppColors.greyColor,
- borderColor: AppColors.greyColor,
- textColor: AppColors.blackColor,
- fontSize: 10,
- fontWeight: FontWeight.normal,
- borderRadius: 12,
- padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
- height: 30.h,
- ),
- SizedBox(width: 4.h),
- CustomButton(
- icon: AppAssets.blood_icon,
- iconColor: AppColors.primaryRedColor,
- iconSize: 13.h,
- text: "Blood: ${appState.getUserBloodGroup}",
- onPressed: () {},
- backgroundColor: AppColors.greyColor,
- borderColor: AppColors.greyColor,
- textColor: AppColors.blackColor,
- fontSize: 10,
- fontWeight: FontWeight.normal,
- borderRadius: 12,
- padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
- height: 30.h,
- ),
- // SizedBox(width: 4.h),
- // CustomButton(
- // icon: AppAssets.insurance_active_icon,
- // iconColor: AppColors.successColor,
- // iconSize: 13.h,
- // text: "Insurance Active",
- // onPressed: () {},
- // backgroundColor: AppColors.bgGreenColor.withOpacity(0.20),
- // borderColor: AppColors.bgGreenColor.withOpacity(0.0),
- // textColor: AppColors.blackColor,
- // fontSize: 10,
- // fontWeight: FontWeight.normal,
- // borderRadius: 12,
- // padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
- // height: 30.h,
- // ),
+ CustomTabBar(
+ activeTextColor: Color(0xffED1C2B),
+ activeBackgroundColor: Color(0xffED1C2B).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),
],
- ),
- SizedBox(height: 8.h),
+ onTabChange: (index) {
+ print(index);
+ medicalFileVM.onTabChanged(index);
+ },
+ ).paddingSymmetrical(24.h, 0.0),
+ SizedBox(height: 24.h),
+ getSelectedTabData(medicalFileVM.selectedTabIndex),
],
- ),
- ),
- ).paddingSymmetrical(24.h, 0.0),
- SizedBox(height: 16.h),
- Consumer(builder: (context, medicalFileVM, child) {
- return Column(
- children: [
- CustomTabBar(
- activeTextColor: Color(0xffED1C2B),
- activeBackgroundColor: Color(0xffED1C2B).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) {
- print(index);
- medicalFileVM.onTabChanged(index);
- },
- ).paddingSymmetrical(24.h, 0.0),
- SizedBox(height: 24.h),
- getSelectedTabData(medicalFileVM.selectedTabIndex),
- ],
- );
- }),
- ],
+ );
+ }),
+ ],
+ ),
),
),
);
@@ -224,6 +248,7 @@ class _MedicalFilePageState extends State {
case 0:
//General Tab Data
return Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
@@ -244,6 +269,320 @@ class _MedicalFilePageState extends State {
),
);
}),
+ Consumer(builder: (context, myAppointmentsVM, child) {
+ return SizedBox(
+ height: 200.h,
+ child: ListView.separated(
+ scrollDirection: Axis.horizontal,
+ padding: EdgeInsets.only(top: 16.h, left: 24.h, right: 24.h, bottom: 0.h),
+ shrinkWrap: true,
+ itemCount: myAppointmentsVM.isMyAppointmentsLoading ? 5 : myAppointmentsVM.patientAppointmentsHistoryList.length,
+ itemBuilder: (context, index) {
+ return AnimationConfiguration.staggeredList(
+ position: index,
+ duration: const Duration(milliseconds: 500),
+ child: SlideAnimation(
+ horizontalOffset: 100.0,
+ child: FadeInAnimation(
+ child: AnimatedContainer(
+ duration: Duration(milliseconds: 300),
+ curve: Curves.easeInOut,
+ child: myAppointmentsVM.isMyAppointmentsLoading
+ ? MedicalFileAppointmentCard(
+ patientAppointmentHistoryResponseModel: PatientAppointmentHistoryResponseModel(),
+ myAppointmentsViewModel: myAppointmentsVM,
+ )
+ : MedicalFileAppointmentCard(
+ patientAppointmentHistoryResponseModel: myAppointmentsVM.patientAppointmentsHistoryList[index],
+ myAppointmentsViewModel: myAppointmentsViewModel,
+ ),
+ ),
+ ),
+ ),
+ );
+ },
+ separatorBuilder: (BuildContext cxt, int index) => SizedBox(width: 12.h),
+ ),
+ );
+ }),
+ SizedBox(height: 24.h),
+ "Lab & Radiology".needTranslation.toText18(isBold: true).paddingSymmetrical(24.h, 0.h),
+ SizedBox(height: 16.h),
+ Row(
+ children: [
+ Expanded(
+ child: LabRadCard(
+ icon: AppAssets.lab_result_icon,
+ labelText: LocaleKeys.labResults.tr(context: context),
+ labOrderTests: ["Complete blood count", "Creatinine", "Blood Sugar"],
+ ),
+ ),
+ SizedBox(width: 16.h),
+ Expanded(
+ child: LabRadCard(
+ icon: AppAssets.radiology_icon,
+ labelText: LocaleKeys.radiology.tr(context: context),
+ labOrderTests: ["Chest X-ray", "Abdominal Ultrasound", "Dental X-ray"],
+ ),
+ ),
+ ],
+ ).paddingSymmetrical(24.h, 0.h),
+ SizedBox(height: 24.h),
+ "Active Medications & Prescriptions".needTranslation.toText18(isBold: true).paddingSymmetrical(24.h, 0.h),
+ SizedBox(height: 16.h),
+ Consumer(builder: (context, prescriptionVM, child) {
+ return prescriptionVM.isPrescriptionsOrdersLoading
+ ? const MoviesShimmerWidget().paddingSymmetrical(24.h, 0.h)
+ : prescriptionVM.patientPrescriptionOrders.isNotEmpty
+ ? Container(
+ decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
+ color: Colors.white,
+ borderRadius: 20.h,
+ ),
+ child: Padding(
+ padding: EdgeInsets.all(16.h),
+ child: Column(
+ children: [
+ ListView.separated(
+ itemCount: prescriptionVM.patientPrescriptionOrders.length,
+ shrinkWrap: true,
+ padding: const EdgeInsets.only(left: 0, right: 8),
+ physics: NeverScrollableScrollPhysics(),
+ itemBuilder: (context, index) {
+ return AnimationConfiguration.staggeredList(
+ position: index,
+ duration: const Duration(milliseconds: 500),
+ child: SlideAnimation(
+ verticalOffset: 100.0,
+ child: FadeInAnimation(
+ child: Row(
+ children: [
+ Image.network(
+ prescriptionVM.patientPrescriptionOrders[index].doctorImageURL!,
+ width: 63.h,
+ height: 63.h,
+ fit: BoxFit.fill,
+ ).circle(100),
+ SizedBox(width: 16.h),
+ Expanded(
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ prescriptionVM.patientPrescriptionOrders[index].doctorName!.toText16(isBold: true),
+ SizedBox(height: 4.h),
+ Wrap(
+ direction: Axis.horizontal,
+ spacing: 3.h,
+ runSpacing: 4.h,
+ children: [
+ AppCustomChipWidget(labelText: prescriptionVM.patientPrescriptionOrders[index].clinicDescription!),
+ AppCustomChipWidget(
+ icon: AppAssets.doctor_calendar_icon,
+ labelText: DateUtil.formatDateToDate(DateUtil.convertStringToDate(prescriptionVM.patientPrescriptionOrders[index].appointmentDate), false),
+ ),
+ ],
+ ),
+ ],
+ ),
+ ),
+ SizedBox(width: 40.h),
+ Utils.buildSvgWithAssets(icon: AppAssets.forward_arrow_icon, width: 15.h, height: 15.h, fit: BoxFit.contain, iconColor: AppColors.textColor),
+ ],
+ ).onPress(() {
+ prescriptionVM.setPrescriptionsDetailsLoading();
+ Navigator.of(context).push(
+ FadePage(
+ page: PrescriptionDetailPage(prescriptionsResponseModel: prescriptionVM.patientPrescriptionOrders[index]),
+ ),
+ );
+ }),
+ ),
+ ),
+ );
+ },
+ separatorBuilder: (BuildContext cxt, int index) => SizedBox(height: 16.h),
+ ),
+ SizedBox(height: 16.h),
+ const Divider(color: AppColors.dividerColor),
+ SizedBox(height: 16.h),
+ Row(
+ children: [
+ Expanded(
+ child: CustomButton(
+ text: "All Prescriptions".needTranslation,
+ onPressed: () {
+ Navigator.of(context).push(
+ FadePage(
+ page: PrescriptionsListPage(),
+ ),
+ );
+ },
+ backgroundColor: AppColors.secondaryLightRedColor,
+ borderColor: AppColors.secondaryLightRedColor,
+ textColor: AppColors.primaryRedColor,
+ fontSize: 14,
+ fontWeight: FontWeight.w500,
+ borderRadius: 12.h,
+ height: 40.h,
+ icon: AppAssets.requests,
+ iconColor: AppColors.primaryRedColor,
+ iconSize: 16.h,
+ ),
+ ),
+ SizedBox(width: 10.h),
+ Expanded(
+ child: CustomButton(
+ text: "All Medications".needTranslation,
+ onPressed: () {},
+ backgroundColor: AppColors.secondaryLightRedColor,
+ borderColor: AppColors.secondaryLightRedColor,
+ textColor: AppColors.primaryRedColor,
+ fontSize: 14,
+ fontWeight: FontWeight.w500,
+ borderRadius: 12.h,
+ height: 40.h,
+ icon: AppAssets.all_medications_icon,
+ iconColor: AppColors.primaryRedColor,
+ iconSize: 16.h,
+ ),
+ ),
+ ],
+ ),
+ ],
+ ),
+ ),
+ ).paddingSymmetrical(24.h, 0.h)
+ : SizedBox.shrink();
+ }),
+ SizedBox(height: 24.h),
+ //My Doctor Section
+ Row(
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ children: [
+ LocaleKeys.myDoctor.tr(context: context).toText18(isBold: true),
+ Row(
+ children: [
+ LocaleKeys.viewAll.tr().toText12(color: AppColors.primaryRedColor, fontWeight: FontWeight.w500),
+ SizedBox(width: 2.h),
+ Icon(Icons.arrow_forward_ios, color: AppColors.primaryRedColor, size: 10.h),
+ ],
+ ).onPress(() {
+ myAppointmentsViewModel.setIsPatientMyDoctorsLoading(true);
+ myAppointmentsViewModel.getPatientMyDoctors();
+ Navigator.of(context).push(
+ FadePage(
+ page: MyDoctorsPage(),
+ ),
+ );
+ }),
+ ],
+ ).paddingSymmetrical(24.h, 0.h),
+ SizedBox(height: 16.h),
+ Consumer(builder: (context, myAppointmentsVM, child) {
+ return SizedBox(
+ height: 120.h,
+ child: ListView.separated(
+ scrollDirection: Axis.horizontal,
+ itemCount: myAppointmentsVM.isPatientMyDoctorsLoading ? 5 : myAppointmentsVM.patientMyDoctorsList.length,
+ shrinkWrap: true,
+ padding: EdgeInsets.only(left: 24.h, right: 24.h),
+ itemBuilder: (context, index) {
+ return myAppointmentsVM.isPatientMyDoctorsLoading
+ ? SizedBox(
+ width: 80.h,
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.center,
+ children: [
+ Image.network(
+ "https://hmgwebservices.com/Images/MobileImages/DUBAI/unkown_female.png",
+ width: 64.h,
+ height: 64.h,
+ fit: BoxFit.fill,
+ ).circle(100).toShimmer2(isShow: true, radius: 50.h),
+ SizedBox(height: 8.h),
+ Expanded(
+ child: ("Dr. John Smith Smith Smith").toString().toText12(fontWeight: FontWeight.w500, isCenter: true, maxLine: 2).toShimmer2(isShow: true),
+ ),
+ ],
+ ),
+ )
+ : AnimationConfiguration.staggeredList(
+ position: index,
+ duration: const Duration(milliseconds: 1000),
+ child: SlideAnimation(
+ horizontalOffset: 100.0,
+ child: FadeInAnimation(
+ child: SizedBox(
+ width: 80.h,
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.center,
+ children: [
+ Image.network(
+ myAppointmentsVM.patientMyDoctorsList[index].doctorImageURL!,
+ width: 64.h,
+ height: 64.h,
+ fit: BoxFit.fill,
+ ).circle(100).toShimmer2(isShow: false, radius: 50.h),
+ SizedBox(height: 8.h),
+ Expanded(
+ child: (myAppointmentsVM.patientMyDoctorsList[index].doctorName)
+ .toString()
+ .toText12(fontWeight: FontWeight.w500, isCenter: true, maxLine: 2)
+ .toShimmer2(isShow: false),
+ ),
+ ],
+ ),
+ ),
+ ),
+ ),
+ );
+ },
+ separatorBuilder: (BuildContext cxt, int index) => SizedBox(width: 8.h),
+ ),
+ );
+ }),
+ SizedBox(height: 24.h),
+ "Others".needTranslation.toText18(isBold: true).paddingSymmetrical(24.h, 0.h),
+ SizedBox(height: 16.h),
+ GridView(
+ gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 3, crossAxisSpacing: 13, mainAxisSpacing: 13),
+ physics: NeverScrollableScrollPhysics(),
+ padding: EdgeInsets.zero,
+ shrinkWrap: true,
+ children: [
+ MedicalFileCard(
+ label: "Eye Test Results".needTranslation,
+ textColor: AppColors.blackColor,
+ backgroundColor: AppColors.whiteColor,
+ svgIcon: AppAssets.eye_result_icon,
+ isLargeText: true,
+ iconSize: 40.h,
+ ),
+ MedicalFileCard(
+ label: "Allergy Info".needTranslation,
+ textColor: AppColors.blackColor,
+ backgroundColor: AppColors.whiteColor,
+ svgIcon: AppAssets.allergy_info_icon,
+ isLargeText: true,
+ iconSize: 40.h,
+ ),
+ MedicalFileCard(
+ label: "Vaccine Info".needTranslation,
+ textColor: AppColors.blackColor,
+ backgroundColor: AppColors.whiteColor,
+ svgIcon: AppAssets.vaccine_info_icon,
+ isLargeText: true,
+ iconSize: 40.h,
+ ).onPress(() {
+ Navigator.of(context).push(
+ FadePage(
+ page: VaccineListPage(),
+ ),
+ );
+ }),
+ ],
+ ).paddingSymmetrical(24.h, 0.0),
+ SizedBox(height: 24.h),
],
);
case 1:
@@ -264,17 +603,113 @@ class _MedicalFilePageState extends State {
padding: EdgeInsets.only(top: 12),
shrinkWrap: true,
children: [
- MedicalFileCard(label: "Update Insurance".needTranslation, textColor: AppColors.blackColor, backgroundColor: AppColors.whiteColor, svgIcon: AppAssets.eye_result_icon),
- MedicalFileCard(label: "Insurance Approvals".needTranslation, textColor: AppColors.blackColor, backgroundColor: AppColors.whiteColor, svgIcon: AppAssets.eye_result_icon),
- MedicalFileCard(label: "My Invoices List".needTranslation, textColor: AppColors.blackColor, backgroundColor: AppColors.whiteColor, svgIcon: AppAssets.eye_result_icon),
- MedicalFileCard(label: "Ancillary Orders List".needTranslation, textColor: AppColors.blackColor, backgroundColor: AppColors.whiteColor, svgIcon: AppAssets.eye_result_icon),
+ MedicalFileCard(
+ label: "Update Insurance".needTranslation,
+ textColor: AppColors.blackColor,
+ backgroundColor: AppColors.whiteColor,
+ svgIcon: AppAssets.eye_result_icon,
+ isLargeText: false,
+ iconSize: 36.h)
+ .onPress(() {
+ Navigator.of(context).push(
+ FadePage(
+ page: InsuranceHomePage(),
+ ),
+ );
+ }),
+ MedicalFileCard(
+ label: "Insurance Approvals".needTranslation,
+ textColor: AppColors.blackColor,
+ backgroundColor: AppColors.whiteColor,
+ svgIcon: AppAssets.eye_result_icon,
+ isLargeText: false,
+ iconSize: 36.h),
+ MedicalFileCard(
+ label: "My Invoices List".needTranslation,
+ textColor: AppColors.blackColor,
+ backgroundColor: AppColors.whiteColor,
+ svgIcon: AppAssets.eye_result_icon,
+ isLargeText: false,
+ iconSize: 36.h),
+ MedicalFileCard(
+ label: "Ancillary Orders List".needTranslation,
+ textColor: AppColors.blackColor,
+ backgroundColor: AppColors.whiteColor,
+ svgIcon: AppAssets.eye_result_icon,
+ isLargeText: false,
+ iconSize: 36.h),
],
).paddingSymmetrical(24.h, 0.0),
SizedBox(height: 16.h),
],
);
case 2:
- return Container();
+ // Requests Tab Data
+ return Column(
+ children: [
+ Consumer(builder: (context, medicalFileVM, child) {
+ return medicalFileVM.isPatientSickLeaveListLoading
+ ? PatientSickLeaveCard(
+ patientSickLeavesResponseModel: PatientSickLeavesResponseModel(),
+ isLoading: true,
+ ).paddingSymmetrical(24.h, 0.0)
+ : medicalFileVM.patientSickLeaveList.isNotEmpty
+ ? PatientSickLeaveCard(
+ patientSickLeavesResponseModel: medicalFileVM.patientSickLeaveList.first,
+ isLoading: false,
+ ).paddingSymmetrical(24.h, 0.0)
+ : SizedBox.shrink();
+ }),
+ SizedBox(height: 16.h),
+ GridView(
+ gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 3, crossAxisSpacing: 13, mainAxisSpacing: 13),
+ physics: NeverScrollableScrollPhysics(),
+ padding: EdgeInsets.zero,
+ shrinkWrap: true,
+ children: [
+ MedicalFileCard(
+ label: LocaleKeys.monthlyReports.tr(context: context),
+ textColor: AppColors.blackColor,
+ backgroundColor: AppColors.whiteColor,
+ svgIcon: AppAssets.eye_result_icon,
+ isLargeText: false,
+ iconSize: 40.h,
+ ),
+ MedicalFileCard(
+ label: "Medical Reports".needTranslation,
+ textColor: AppColors.blackColor,
+ backgroundColor: AppColors.whiteColor,
+ svgIcon: AppAssets.allergy_info_icon,
+ isLargeText: false,
+ iconSize: 40.h,
+ ).onPress(() {
+ medicalFileViewModel.setIsPatientMedicalReportsLoading(true);
+ medicalFileViewModel.getPatientMedicalReportList();
+ Navigator.of(context).push(
+ FadePage(
+ page: MedicalReportsPage(),
+ ),
+ );
+ }),
+ MedicalFileCard(
+ label: "Sick Leave Report".needTranslation,
+ textColor: AppColors.blackColor,
+ backgroundColor: AppColors.whiteColor,
+ svgIcon: AppAssets.vaccine_info_icon,
+ isLargeText: false,
+ iconSize: 40.h,
+ ).onPress(() {
+ Navigator.of(context).push(
+ FadePage(
+ page: PatientSickleavesListPage(),
+ ),
+ );
+ }),
+ ],
+ ).paddingSymmetrical(24.h, 0.0),
+ SizedBox(height: 24.h),
+ ],
+ );
case 3:
return Container();
default:
diff --git a/lib/presentation/medical_file/medical_reports_page.dart b/lib/presentation/medical_file/medical_reports_page.dart
new file mode 100644
index 0000000..ea3c34d
--- /dev/null
+++ b/lib/presentation/medical_file/medical_reports_page.dart
@@ -0,0 +1,94 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_staggered_animations/flutter_staggered_animations.dart';
+import 'package:hmg_patient_app_new/core/utils/size_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/medical_file_view_model.dart';
+import 'package:hmg_patient_app_new/features/medical_file/models/patient_medical_response_model.dart';
+import 'package:hmg_patient_app_new/presentation/lab/collapsing_list_view.dart';
+import 'package:hmg_patient_app_new/presentation/medical_file/widgets/patient_medical_report_card.dart';
+import 'package:hmg_patient_app_new/theme/colors.dart';
+import 'package:hmg_patient_app_new/widgets/custom_tab_bar.dart';
+import 'package:provider/provider.dart';
+
+class MedicalReportsPage extends StatefulWidget {
+ const MedicalReportsPage({super.key});
+
+ @override
+ State createState() => _MedicalReportsPageState();
+}
+
+class _MedicalReportsPageState extends State {
+ late MedicalFileViewModel medicalFileViewModel;
+
+ @override
+ Widget build(BuildContext context) {
+ medicalFileViewModel = Provider.of(context, listen: false);
+ return Scaffold(
+ backgroundColor: AppColors.bgScaffoldColor,
+ body: CollapsingListView(
+ title: "Medical Reports".needTranslation,
+ child: SingleChildScrollView(
+ child: Column(
+ children: [
+ SizedBox(height: 16.h),
+ CustomTabBar(
+ activeTextColor: Color(0xffED1C2B),
+ activeBackgroundColor: Color(0xffED1C2B).withValues(alpha: .1),
+ tabs: [
+ CustomTabBarModel(null, "Requested".needTranslation),
+ CustomTabBarModel(null, "Ready".needTranslation),
+ CustomTabBarModel(null, "Cancelled".needTranslation),
+ ],
+ onTabChange: (index) {
+ medicalFileViewModel.onMedicalReportTabChange(index);
+ },
+ ).paddingSymmetrical(24.h, 0.h),
+ Consumer(builder: (context, medicalFileVM, child) {
+ return ListView.separated(
+ padding: EdgeInsets.only(top: 24.h),
+ shrinkWrap: true,
+ physics: NeverScrollableScrollPhysics(),
+ itemCount: medicalFileViewModel.isPatientMedicalReportsListLoading ? 3 : medicalFileViewModel.patientMedicalReportList.length,
+ // medicalFileViewModel.patientMedicalReportList.isNotEmpty
+ // ? medicalFileViewModel.patientMedicalReportList.length
+ // : 1,
+ itemBuilder: (context, index) {
+ return medicalFileViewModel.isPatientMedicalReportsListLoading
+ ? PatientMedicalReportCard(
+ patientMedicalReportResponseModel: PatientMedicalReportResponseModel(),
+ medicalFileViewModel: medicalFileVM,
+ isLoading: true,
+ ).paddingSymmetrical(24.h, 0.h)
+ : AnimationConfiguration.staggeredList(
+ position: index,
+ duration: const Duration(milliseconds: 500),
+ child: SlideAnimation(
+ verticalOffset: 100.0,
+ child: FadeInAnimation(
+ child: AnimatedContainer(
+ duration: Duration(milliseconds: 300),
+ curve: Curves.easeInOut,
+ decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24.h, hasShadow: true),
+ child: PatientMedicalReportCard(
+ patientMedicalReportResponseModel: medicalFileVM.patientMedicalReportList[index],
+ medicalFileViewModel: medicalFileVM,
+
+ isLoading: false,
+ ),
+ ).paddingSymmetrical(24.h, 0.h),
+ ),
+ ),
+ );
+ },
+ separatorBuilder: (BuildContext cxt, int index) => SizedBox(height: 16.h),
+ );
+ }),
+ SizedBox(height: 24.h),
+ ],
+ ),
+ ),
+ ),
+ );
+ }
+}
diff --git a/lib/presentation/medical_file/patient_sickleaves_list_page.dart b/lib/presentation/medical_file/patient_sickleaves_list_page.dart
new file mode 100644
index 0000000..9950779
--- /dev/null
+++ b/lib/presentation/medical_file/patient_sickleaves_list_page.dart
@@ -0,0 +1,88 @@
+import 'dart:async';
+
+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/utils/size_utils.dart';
+import 'package:hmg_patient_app_new/extensions/widget_extensions.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/patient_sickleave_response_model.dart';
+import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
+import 'package:hmg_patient_app_new/presentation/lab/collapsing_list_view.dart';
+import 'package:hmg_patient_app_new/theme/colors.dart';
+import 'package:provider/provider.dart';
+
+import 'widgets/patient_sick_leave_card.dart';
+
+class PatientSickleavesListPage extends StatefulWidget {
+ const PatientSickleavesListPage({super.key});
+
+ @override
+ State createState() => _PatientSickleavesListPageState();
+}
+
+class _PatientSickleavesListPageState extends State {
+ late MedicalFileViewModel medicalFileViewModel;
+
+ @override
+ void initState() {
+ scheduleMicrotask(() {
+ medicalFileViewModel.setIsPatientSickLeaveListLoading(true);
+ medicalFileViewModel.getPatientSickLeaveList(onError: (error) {
+ Navigator.of(context).pop();
+ Navigator.of(context).pop();
+ });
+ });
+ super.initState();
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ medicalFileViewModel = Provider.of(context, listen: false);
+ return Scaffold(
+ backgroundColor: AppColors.bgScaffoldColor,
+ body: CollapsingListView(
+ title: "${LocaleKeys.sick.tr(context: context)} ${LocaleKeys.sickSubtitle.tr(context: context)}",
+ child: SingleChildScrollView(
+ child: Consumer(builder: (context, medicalFileVM, child) {
+ return Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ ListView.separated(
+ scrollDirection: Axis.vertical,
+ itemCount: medicalFileVM.isPatientSickLeaveListLoading ? 3 : medicalFileVM.patientSickLeaveList.length,
+ shrinkWrap: true,
+ physics: NeverScrollableScrollPhysics(),
+ itemBuilder: (context, index) {
+ return medicalFileVM.isPatientSickLeaveListLoading
+ ? PatientSickLeaveCard(
+ patientSickLeavesResponseModel: PatientSickLeavesResponseModel(),
+ isLoading: true,
+ ).paddingSymmetrical(24.h, 0.0)
+ : medicalFileVM.patientSickLeaveList.isNotEmpty
+ ? AnimationConfiguration.staggeredList(
+ position: index,
+ duration: const Duration(milliseconds: 1000),
+ child: SlideAnimation(
+ verticalOffset: 100.0,
+ child: FadeInAnimation(
+ child: PatientSickLeaveCard(
+ patientSickLeavesResponseModel: medicalFileVM.patientSickLeaveList.first,
+ isLoading: false,
+ ).paddingSymmetrical(24.h, 0.0),
+ ),
+ ),
+ )
+ : SizedBox.shrink();
+ },
+ separatorBuilder: (BuildContext cxt, int index) => SizedBox(height: 8.h),
+ ),
+ SizedBox(height: 60.h),
+ ],
+ );
+ }),
+ ),
+ ),
+ );
+ }
+}
diff --git a/lib/presentation/medical_file/vaccine_list_page.dart b/lib/presentation/medical_file/vaccine_list_page.dart
new file mode 100644
index 0000000..0cf48d6
--- /dev/null
+++ b/lib/presentation/medical_file/vaccine_list_page.dart
@@ -0,0 +1,181 @@
+import 'dart:async';
+
+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/utils/date_util.dart';
+import 'package:hmg_patient_app_new/core/utils/size_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/medical_file_view_model.dart';
+import 'package:hmg_patient_app_new/presentation/lab/collapsing_list_view.dart';
+import 'package:hmg_patient_app_new/theme/colors.dart';
+import 'package:provider/provider.dart';
+
+import '../../widgets/chip/app_custom_chip_widget.dart';
+
+class VaccineListPage extends StatefulWidget {
+ const VaccineListPage({super.key});
+
+ @override
+ State createState() => _VaccineListPageState();
+}
+
+class _VaccineListPageState extends State {
+ late MedicalFileViewModel medicalFileViewModel;
+
+ @override
+ void initState() {
+ scheduleMicrotask(() {
+ medicalFileViewModel.setIsPatientVaccineListLoading(true);
+ medicalFileViewModel.getPatientVaccinesList(onError: (error) {
+ Navigator.of(context).pop();
+ Navigator.of(context).pop();
+ });
+ });
+ super.initState();
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ medicalFileViewModel = Provider.of(context, listen: false);
+ return Scaffold(
+ backgroundColor: AppColors.bgScaffoldColor,
+ body: CollapsingListView(
+ title: "Vaccine Info".needTranslation,
+ child: SingleChildScrollView(
+ child: Consumer(builder: (context, medicalFileVM, child) {
+ return Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ SizedBox(height: 16.h),
+ ListView.separated(
+ scrollDirection: Axis.vertical,
+ itemCount: medicalFileVM.isPatientVaccineListLoading ? 5 : medicalFileVM.patientVaccineList.length,
+ shrinkWrap: true,
+ physics: NeverScrollableScrollPhysics(),
+ padding: EdgeInsets.only(left: 24.h, right: 24.h),
+ itemBuilder: (context, index) {
+ return medicalFileVM.isPatientVaccineListLoading
+ ? Container(
+ decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
+ color: AppColors.whiteColor,
+ borderRadius: 20.h,
+ hasShadow: true,
+ ),
+ child: Padding(
+ padding: EdgeInsets.all(14.h),
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Row(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Image.network(
+ "https://hmgwebservices.com/Images/MobileImages/DUBAI/unkown_female.png",
+ width: 63.h,
+ height: 63.h,
+ fit: BoxFit.fill,
+ ).circle(100).toShimmer2(isShow: true),
+ SizedBox(width: 16.h),
+ Expanded(
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ "Dr John Smith".toText16(isBold: true).toShimmer2(isShow: true),
+ SizedBox(height: 8.h),
+ Wrap(
+ direction: Axis.horizontal,
+ spacing: 3.h,
+ runSpacing: 4.h,
+ children: [
+ AppCustomChipWidget(labelText: "").toShimmer2(isShow: true, width: 16.h),
+ AppCustomChipWidget(labelText: "").toShimmer2(isShow: true, width: 16.h),
+ ],
+ ),
+ ],
+ ),
+ ),
+ ],
+ ),
+ ],
+ ),
+ ),
+ )
+ : AnimationConfiguration.staggeredList(
+ position: index,
+ duration: const Duration(milliseconds: 1000),
+ child: SlideAnimation(
+ verticalOffset: 100.0,
+ child: FadeInAnimation(
+ child: Container(
+ decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
+ color: AppColors.whiteColor,
+ borderRadius: 20.h,
+ hasShadow: true,
+ ),
+ child: Padding(
+ padding: EdgeInsets.all(14.h),
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Row(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ // Image.network(
+ // medicalFileVM.patientVaccineList[index].doctorImageURL,
+ // width: 63.h,
+ // height: 63.h,
+ // fit: BoxFit.fill,
+ // ).circle(100).toShimmer2(isShow: false),
+ SizedBox(width: 16.h),
+ Expanded(
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ (medicalFileVM.patientVaccineList[index].doctorName).toString().toText16(isBold: true).toShimmer2(isShow: false),
+ SizedBox(height: 8.h),
+ Wrap(
+ direction: Axis.horizontal,
+ spacing: 3.h,
+ runSpacing: 4.h,
+ children: [
+ AppCustomChipWidget(
+ icon: AppAssets.doctor_calendar_icon,
+ labelText: DateUtil.formatDateToDate(DateUtil.convertStringToDate(medicalFileVM.patientVaccineList[index].vaccinationDate), false)),
+ AppCustomChipWidget(labelText: medicalFileVM.patientVaccineList[index].vaccineName).toShimmer2(isShow: false, width: 16.h),
+ AppCustomChipWidget(labelText: medicalFileVM.patientVaccineList[index].clinicName).toShimmer2(isShow: false, width: 16.h),
+ AppCustomChipWidget(labelText: medicalFileVM.patientVaccineList[index].projectName).toShimmer2(isShow: false, width: 16.h),
+ ],
+ ),
+ ],
+ ),
+ ),
+ ],
+ ),
+ // Row(
+ // mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ // children: [
+ // "".toText16(),
+ // Utils.buildSvgWithAssets(icon: AppAssets.forward_arrow_icon, width: 15.h, height: 15.h, fit: BoxFit.contain, iconColor: AppColors.textColor),
+ // ],
+ // ),
+ ],
+ ),
+ ),
+ ),
+ ),
+ ),
+ );
+ },
+ separatorBuilder: (BuildContext cxt, int index) => SizedBox(height: 16.h),
+ ),
+ SizedBox(height: 60.h),
+ ],
+ );
+ }),
+ ),
+ ),
+ );
+ }
+}
diff --git a/lib/presentation/medical_file/widgets/lab_rad_card.dart b/lib/presentation/medical_file/widgets/lab_rad_card.dart
new file mode 100644
index 0000000..aa53b2f
--- /dev/null
+++ b/lib/presentation/medical_file/widgets/lab_rad_card.dart
@@ -0,0 +1,65 @@
+import 'package:flutter/material.dart';
+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/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/theme/colors.dart';
+
+class LabRadCard extends StatelessWidget {
+ LabRadCard({super.key, required this.icon, required this.labelText, required this.labOrderTests});
+
+ String icon;
+ String labelText;
+ List labOrderTests = [];
+
+ @override
+ Widget build(BuildContext context) {
+ return Container(
+ decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24.h, hasShadow: false),
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Row(
+ children: [
+ Utils.buildSvgWithAssets(
+ icon: icon,
+ width: 40.h,
+ height: 40.h,
+ fit: BoxFit.contain,
+ ).toShimmer2(isShow: false, radius: 12.h),
+ SizedBox(width: 8.h),
+ labelText.toText14(isBold: true).toShimmer2(isShow: false, radius: 6.h, height: 32.h),
+ ],
+ ),
+ SizedBox(height: 16.h),
+ ListView.separated(
+ scrollDirection: Axis.vertical,
+ padding: EdgeInsets.zero,
+ physics: NeverScrollableScrollPhysics(),
+ shrinkWrap: true,
+ itemBuilder: (cxt, index) {
+ return labOrderTests[index].toText12(isBold: true, maxLine: 1).toShimmer2(isShow: false, radius: 6.h, height: 24.h, width: 120.h);
+ },
+ separatorBuilder: (cxt, index) => SizedBox(height: 8.h),
+ itemCount: labOrderTests.length,
+ ),
+ SizedBox(height: 16.h),
+ Row(
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ children: [
+ SizedBox.shrink(),
+ Utils.buildSvgWithAssets(
+ icon: AppAssets.forward_arrow_icon,
+ width: 15.h,
+ height: 15.h,
+ fit: BoxFit.contain,
+ iconColor: AppColors.textColor
+ ).toShimmer2(isShow: false, radius: 12.h),
+ ],
+ )
+ ],
+ ).paddingAll(16.h),
+ );
+ }
+}
diff --git a/lib/presentation/medical_file/widgets/medical_file_appointment_card.dart b/lib/presentation/medical_file/widgets/medical_file_appointment_card.dart
new file mode 100644
index 0000000..48cc328
--- /dev/null
+++ b/lib/presentation/medical_file/widgets/medical_file_appointment_card.dart
@@ -0,0 +1,181 @@
+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/utils/date_util.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';
+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/my_appointments/utils/appointment_type.dart';
+import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
+import 'package:hmg_patient_app_new/presentation/appointments/appointment_details_page.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/transitions/fade_page.dart';
+
+class MedicalFileAppointmentCard extends StatelessWidget {
+ MedicalFileAppointmentCard({super.key, required this.patientAppointmentHistoryResponseModel, required this.myAppointmentsViewModel});
+
+ PatientAppointmentHistoryResponseModel patientAppointmentHistoryResponseModel;
+ MyAppointmentsViewModel myAppointmentsViewModel;
+
+ @override
+ Widget build(BuildContext context) {
+ return Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ CustomButton(
+ text: DateUtil.formatDateToDate(DateUtil.convertStringToDate(patientAppointmentHistoryResponseModel.appointmentDate), false),
+ onPressed: () {},
+ backgroundColor: AppointmentType.isArrived(patientAppointmentHistoryResponseModel) ? AppColors.greyColor : AppColors.secondaryLightRedColor,
+ borderColor: AppointmentType.isArrived(patientAppointmentHistoryResponseModel) ? AppColors.greyLightColor : AppColors.secondaryLightRedColor,
+ textColor: AppointmentType.isArrived(patientAppointmentHistoryResponseModel) ? AppColors.textColor : AppColors.primaryRedColor,
+ fontSize: 12,
+ fontWeight: FontWeight.w500,
+ borderRadius: 12.h,
+ padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
+ height: 40.h,
+ icon: AppointmentType.isArrived(patientAppointmentHistoryResponseModel) ? AppAssets.appointment_calendar_icon : AppAssets.alarm_clock_icon,
+ iconColor: AppointmentType.isArrived(patientAppointmentHistoryResponseModel) ? AppColors.textColor : AppColors.primaryRedColor,
+ iconSize: 16.h,
+ ).toShimmer2(isShow: myAppointmentsViewModel.isMyAppointmentsLoading),
+ SizedBox(height: 16.h),
+ Container(
+ decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24.h, hasShadow: true),
+ width: 200.h,
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Row(
+ children: [
+ Image.network(
+ patientAppointmentHistoryResponseModel.doctorImageURL ?? "https://hmgwebservices.com/Images/MobileImages/DUBAI/unkown_female.png",
+ width: 25.h,
+ height: 27.h,
+ fit: BoxFit.fill,
+ ).circle(100).toShimmer2(isShow: myAppointmentsViewModel.isMyAppointmentsLoading),
+ SizedBox(width: 8.h),
+ Expanded(
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ (patientAppointmentHistoryResponseModel.doctorNameObj ?? "").toText14(isBold: true, maxlines: 1).toShimmer2(isShow: myAppointmentsViewModel.isMyAppointmentsLoading),
+ (patientAppointmentHistoryResponseModel.clinicName ?? "")
+ .toText12(maxLine: 1, fontWeight: FontWeight.w500, color: AppColors.greyTextColor)
+ .toShimmer2(isShow: myAppointmentsViewModel.isMyAppointmentsLoading),
+ ],
+ ),
+ ),
+ ],
+ ),
+ SizedBox(height: 12.h),
+ Row(
+ children: [
+ myAppointmentsViewModel.isMyAppointmentsLoading
+ ? Container().toShimmer2(isShow: true, height: 40.h, width: 100.h, radius: 12.h)
+ : Expanded(
+ flex: 6,
+ child: AppointmentType.isArrived(patientAppointmentHistoryResponseModel)
+ ? getArrivedAppointmentButton(context).toShimmer2(isShow: myAppointmentsViewModel.isMyAppointmentsLoading)
+ : CustomButton(
+ text: AppointmentType.getNextActionText(patientAppointmentHistoryResponseModel.nextAction),
+ onPressed: () {
+ Navigator.of(context)
+ .push(FadePage(
+ page: AppointmentDetailsPage(patientAppointmentHistoryResponseModel: patientAppointmentHistoryResponseModel),
+ ))
+ .then((val) {
+ // widget.myAppointmentsViewModel.initAppointmentsViewModel();
+ // widget.myAppointmentsViewModel.getPatientAppointments(true, false);
+ });
+ },
+ backgroundColor: AppointmentType.getNextActionButtonColor(patientAppointmentHistoryResponseModel.nextAction).withOpacity(0.15),
+ borderColor: AppointmentType.getNextActionButtonColor(patientAppointmentHistoryResponseModel.nextAction).withOpacity(0.01),
+ textColor: AppointmentType.getNextActionTextColor(patientAppointmentHistoryResponseModel.nextAction),
+ fontSize: 14,
+ fontWeight: FontWeight.w500,
+ borderRadius: 12,
+ padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
+ height: 40.h,
+ icon: AppointmentType.getNextActionIcon(patientAppointmentHistoryResponseModel.nextAction),
+ iconColor: AppointmentType.getNextActionTextColor(patientAppointmentHistoryResponseModel.nextAction),
+ iconSize: 14.h,
+ ).toShimmer2(isShow: myAppointmentsViewModel.isMyAppointmentsLoading),
+ ),
+ SizedBox(width: 8.h),
+ Expanded(
+ flex: 2,
+ child: Container(
+ height: 40.h,
+ width: 40.h,
+ decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
+ color: AppColors.textColor,
+ borderRadius: 10.h,
+ ),
+ child: Padding(
+ padding: EdgeInsets.all(10.h),
+ child: Utils.buildSvgWithAssets(
+ icon: AppAssets.forward_arrow_icon,
+ width: 10.h,
+ height: 10.h,
+ fit: BoxFit.contain,
+ ),
+ ),
+ ).toShimmer2(isShow: myAppointmentsViewModel.isMyAppointmentsLoading).onPress(() {
+ Navigator.of(context)
+ .push(
+ FadePage(
+ page: AppointmentDetailsPage(patientAppointmentHistoryResponseModel: patientAppointmentHistoryResponseModel),
+ ),
+ )
+ .then((val) {
+ // widget.myAppointmentsViewModel.initAppointmentsViewModel();
+ // widget.myAppointmentsViewModel.getPatientAppointments(true, false);
+ });
+ }),
+ ),
+ ],
+ ),
+ ],
+ ).paddingAll(16.h),
+ ),
+ ],
+ );
+ }
+
+ Widget getArrivedAppointmentButton(BuildContext context) {
+ return DateTime.now().difference(DateUtil.convertStringToDate(patientAppointmentHistoryResponseModel.appointmentDate)).inDays <= 15
+ ? CustomButton(
+ text: LocaleKeys.askDoctor.tr(context: context),
+ onPressed: () {},
+ backgroundColor: AppColors.secondaryLightRedColor,
+ borderColor: AppColors.secondaryLightRedColor,
+ textColor: AppColors.primaryRedColor,
+ fontSize: 14,
+ fontWeight: FontWeight.w500,
+ borderRadius: 12,
+ padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
+ height: 40.h,
+ icon: AppAssets.ask_doctor_icon,
+ iconColor: AppColors.primaryRedColor,
+ iconSize: 16.h,
+ )
+ : CustomButton(
+ text: "Rebook".needTranslation,
+ onPressed: () {},
+ backgroundColor: AppColors.greyColor,
+ borderColor: AppColors.greyColor,
+ textColor: AppColors.blackColor,
+ fontSize: 14,
+ fontWeight: FontWeight.w500,
+ borderRadius: 12,
+ padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
+ height: 40.h,
+ icon: AppAssets.rebook_appointment_icon,
+ iconColor: AppColors.blackColor,
+ iconSize: 16.h,
+ );
+ }
+}
diff --git a/lib/presentation/medical_file/widgets/medical_file_card.dart b/lib/presentation/medical_file/widgets/medical_file_card.dart
index 82f38ec..c4980d9 100644
--- a/lib/presentation/medical_file/widgets/medical_file_card.dart
+++ b/lib/presentation/medical_file/widgets/medical_file_card.dart
@@ -36,7 +36,7 @@ class MedicalFileCard extends StatelessWidget {
children: [
Utils.buildSvgWithAssets(icon: svgIcon, width: iconSize.h, height: iconSize.h, fit: BoxFit.contain),
SizedBox(height: 12.h),
- isLargeText ? label.toText14(color: textColor, isBold: true) : label.toText11(color: textColor, isBold: true),
+ isLargeText ? label.toText14(color: textColor, isBold: true, maxlines: 1) : label.toText11(color: textColor, isBold: true, maxLine: 2),
],
),
),
diff --git a/lib/presentation/medical_file/widgets/patient_medical_report_card.dart b/lib/presentation/medical_file/widgets/patient_medical_report_card.dart
new file mode 100644
index 0000000..eb1730c
--- /dev/null
+++ b/lib/presentation/medical_file/widgets/patient_medical_report_card.dart
@@ -0,0 +1,159 @@
+import 'package:easy_localization/easy_localization.dart';
+import 'package:flutter/cupertino.dart';
+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/utils/date_util.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';
+import 'package:hmg_patient_app_new/features/medical_file/medical_file_view_model.dart';
+import 'package:hmg_patient_app_new/features/medical_file/models/patient_medical_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/common_bottom_sheet.dart';
+import 'package:hmg_patient_app_new/widgets/loader/bottomsheet_loader.dart';
+import 'package:open_filex/open_filex.dart';
+import 'package:share_plus/share_plus.dart';
+
+class PatientMedicalReportCard extends StatelessWidget {
+ PatientMedicalReportCard({super.key, required this.patientMedicalReportResponseModel, required this.medicalFileViewModel, this.isLoading = false});
+
+ PatientMedicalReportResponseModel patientMedicalReportResponseModel;
+ MedicalFileViewModel medicalFileViewModel;
+
+ bool isLoading = true;
+
+ @override
+ Widget build(BuildContext context) {
+ AppState _appState = getIt.get();
+ return Container(
+ decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
+ color: AppColors.whiteColor,
+ borderRadius: 20.h,
+ hasShadow: true,
+ ),
+ child: Padding(
+ padding: EdgeInsets.all(16.h),
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Row(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Image.network(
+ isLoading ? "https://hmgwebservices.com/Images/MobileImages/DUBAI/unkown_female.png" : patientMedicalReportResponseModel.doctorImageURL!,
+ width: 63.h,
+ height: 63.h,
+ fit: BoxFit.fill,
+ ).circle(100).toShimmer2(isShow: isLoading),
+ SizedBox(width: 16.h),
+ Expanded(
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ (isLoading ? "" : patientMedicalReportResponseModel.doctorName!).toText16(isBold: true).toShimmer2(isShow: isLoading),
+ SizedBox(height: 4.h),
+ Wrap(
+ direction: Axis.horizontal,
+ spacing: 3.h,
+ runSpacing: 4.h,
+ children: [
+ AppCustomChipWidget(labelText: isLoading ? "" : patientMedicalReportResponseModel.clinicDescription!).toShimmer2(isShow: isLoading),
+ AppCustomChipWidget(labelText: isLoading ? "" : patientMedicalReportResponseModel.projectName!).toShimmer2(isShow: isLoading),
+ AppCustomChipWidget(
+ icon: AppAssets.doctor_calendar_icon,
+ labelText: isLoading
+ ? ""
+ : "${DateUtil.formatDateToDate(DateUtil.convertStringToDate(patientMedicalReportResponseModel.requestDate), false)}, ${DateUtil.formatDateToTimeLang(DateUtil.convertStringToDate(patientMedicalReportResponseModel.requestDate), false)}")
+ .toShimmer2(isShow: isLoading),
+ AppCustomChipWidget(
+ icon: AppAssets.rating_icon, iconColor: AppColors.ratingColorYellow, labelText: isLoading ? "" : "Rating: ${patientMedicalReportResponseModel.decimalDoctorRate}")
+ .toShimmer2(isShow: isLoading),
+ ],
+ ),
+ ],
+ ),
+ ),
+ ],
+ ),
+ patientMedicalReportResponseModel.status == 2
+ ? Padding(
+ padding: EdgeInsets.only(top: 16.h),
+ child: Row(
+ children: [
+ Expanded(
+ child: CustomButton(
+ text: "Share",
+ onPressed: () {
+ getMedicalReportPDF(true, context, _appState);
+ },
+ backgroundColor: AppColors.secondaryLightRedColor,
+ borderColor: AppColors.secondaryLightRedColor,
+ textColor: AppColors.primaryRedColor,
+ fontSize: 14,
+ fontWeight: FontWeight.w500,
+ borderRadius: 12.h,
+ height: 40.h,
+ icon: AppAssets.download_1,
+ iconColor: AppColors.primaryRedColor,
+ iconSize: 16.h,
+ ).toShimmer2(isShow: isLoading),
+ ),
+ SizedBox(width: 16.h),
+ Expanded(
+ child: CustomButton(
+ text: "Download",
+ onPressed: () async {
+ getMedicalReportPDF(false, context, _appState);
+ },
+ backgroundColor: AppColors.secondaryLightRedColor,
+ borderColor: AppColors.secondaryLightRedColor,
+ textColor: AppColors.primaryRedColor,
+ fontSize: 14,
+ fontWeight: FontWeight.w500,
+ borderRadius: 12.h,
+ height: 40.h,
+ icon: AppAssets.download_1,
+ iconColor: AppColors.primaryRedColor,
+ iconSize: 16.h,
+ ).toShimmer2(isShow: isLoading),
+ ),
+ ],
+ ),
+ )
+ : SizedBox.shrink()
+ ],
+ ),
+ ),
+ );
+ }
+
+ void getMedicalReportPDF(bool isShare, BuildContext context, AppState _appState) async {
+ LoaderBottomSheet.showLoader();
+ await medicalFileViewModel.getPatientMedicalReportPDF(patientMedicalReportResponseModel, _appState.getAuthenticatedUser()!).then((val) async {
+ LoaderBottomSheet.hideLoader();
+ if (medicalFileViewModel.patientMedicalReportPDFBase64.isNotEmpty) {
+ String path = await Utils.createFileFromString(medicalFileViewModel.patientMedicalReportPDFBase64, "pdf");
+ if (isShare) {
+ Share.shareXFiles([XFile(path)], text: "Medical Report");
+ } else {
+ try {
+ OpenFilex.open(path);
+ } catch (ex) {
+ showCommonBottomSheetWithoutHeight(
+ context,
+ child: Utils.getErrorWidget(loadingText: "Cannot open file".needTranslation),
+ callBackFunc: () {},
+ isFullScreen: false,
+ isCloseButtonVisible: true,
+ );
+ }
+ }
+ }
+ });
+ }
+}
diff --git a/lib/presentation/medical_file/widgets/patient_sick_leave_card.dart b/lib/presentation/medical_file/widgets/patient_sick_leave_card.dart
new file mode 100644
index 0000000..438013f
--- /dev/null
+++ b/lib/presentation/medical_file/widgets/patient_sick_leave_card.dart
@@ -0,0 +1,191 @@
+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_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/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';
+import 'package:hmg_patient_app_new/features/medical_file/medical_file_view_model.dart';
+import 'package:hmg_patient_app_new/features/medical_file/models/patient_sickleave_response_model.dart';
+import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
+import 'package:hmg_patient_app_new/presentation/medical_file/patient_sickleaves_list_page.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/common_bottom_sheet.dart';
+import 'package:hmg_patient_app_new/widgets/loader/bottomsheet_loader.dart';
+import 'package:hmg_patient_app_new/widgets/transitions/fade_page.dart';
+import 'package:open_filex/open_filex.dart';
+import 'package:provider/provider.dart';
+
+class PatientSickLeaveCard extends StatelessWidget {
+ PatientSickLeaveCard({super.key, required this.patientSickLeavesResponseModel, this.isLoading = false});
+
+ late MedicalFileViewModel medicalFileViewModel;
+ PatientSickLeavesResponseModel patientSickLeavesResponseModel;
+ bool isLoading;
+
+ @override
+ Widget build(BuildContext context) {
+ AppState _appState = getIt.get();
+ medicalFileViewModel = Provider.of(context, listen: false);
+ return Container(
+ decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24, hasShadow: true),
+ child: Padding(
+ padding: EdgeInsets.all(16.h),
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Row(
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ children: [
+ "${LocaleKeys.sick.tr(context: context)} ${LocaleKeys.sickSubtitle.tr(context: context)}".toText16(isBold: true),
+ AppCustomChipWidget(
+ labelText: isLoading ? "" : getStatusText(context),
+ backgroundColor: getStatusColor().withOpacity(0.15),
+ textColor: getStatusColor(),
+ ).toShimmer2(isShow: isLoading, width: 100.h),
+ ],
+ ),
+ SizedBox(height: 16.h),
+ Row(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Image.network(
+ isLoading ? "https://hmgwebservices.com/Images/MobileImages/DUBAI/unkown_female.png" : patientSickLeavesResponseModel.doctorImageURL!,
+ width: 30.h,
+ height: 30.h,
+ fit: BoxFit.fill,
+ ).circle(100).toShimmer2(isShow: isLoading),
+ SizedBox(width: 16.h),
+ Expanded(
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ (isLoading ? "" : patientSickLeavesResponseModel.doctorName!).toText16(isBold: true).toShimmer2(isShow: isLoading),
+ SizedBox(height: 8.h),
+ Wrap(
+ direction: Axis.horizontal,
+ spacing: 3.h,
+ runSpacing: 4.h,
+ children: [
+ AppCustomChipWidget(
+ icon: AppAssets.doctor_calendar_icon,
+ labelText: DateUtil.formatDateToDate(DateUtil.convertStringToDate(patientSickLeavesResponseModel.appointmentDate), false),
+ ).toShimmer2(isShow: isLoading),
+ AppCustomChipWidget(labelText: isLoading ? "Pending Activation" : patientSickLeavesResponseModel.clinicName!).toShimmer2(isShow: isLoading),
+ ],
+ ),
+ ],
+ ),
+ ),
+ ],
+ ),
+ SizedBox(height: 16.h),
+ Row(
+ children: [
+ isLoading
+ ? Container().toShimmer2(isShow: true, height: 40.h, width: 100.h, radius: 12.h)
+ : Expanded(
+ flex: 6,
+ child: CustomButton(
+ text: "Download Report".needTranslation,
+ onPressed: () async {
+ LoaderBottomSheet.showLoader();
+ await medicalFileViewModel.getPatientSickLeavePDF(patientSickLeavesResponseModel, _appState.getAuthenticatedUser()!).then((val) async {
+ LoaderBottomSheet.hideLoader();
+ if (medicalFileViewModel.patientSickLeavePDFBase64.isNotEmpty) {
+ String path = await Utils.createFileFromString(medicalFileViewModel.patientSickLeavePDFBase64, "pdf");
+ try {
+ OpenFilex.open(path);
+ } catch (ex) {
+ showCommonBottomSheetWithoutHeight(
+ context,
+ child: Utils.getErrorWidget(loadingText: "Cannot open file".needTranslation),
+ callBackFunc: () {},
+ isFullScreen: false,
+ isCloseButtonVisible: true,
+ );
+ }
+ }
+ });
+ },
+ backgroundColor: AppColors.secondaryLightRedColor,
+ borderColor: AppColors.secondaryLightRedColor,
+ textColor: AppColors.primaryRedColor,
+ fontSize: 14,
+ fontWeight: FontWeight.w500,
+ borderRadius: 12,
+ padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
+ height: 40.h,
+ icon: AppAssets.download,
+ iconColor: AppColors.primaryRedColor,
+ iconSize: 14.h,
+ ).toShimmer2(isShow: isLoading),
+ ),
+ SizedBox(width: 8.h),
+ Expanded(
+ flex: 1,
+ child: Container(
+ height: 40.h,
+ width: 40.h,
+ decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
+ color: AppColors.textColor,
+ borderRadius: 10.h,
+ ),
+ child: Padding(
+ padding: EdgeInsets.all(10.h),
+ child: Utils.buildSvgWithAssets(
+ icon: AppAssets.forward_arrow_icon,
+ width: 10.h,
+ height: 10.h,
+ fit: BoxFit.contain,
+ ),
+ ),
+ ).toShimmer2(isShow: isLoading).onPress(() {
+ Navigator.of(context).push(
+ FadePage(
+ page: PatientSickleavesListPage(),
+ ),
+ );
+ }),
+ ),
+ ],
+ ),
+ ],
+ ),
+ ),
+ );
+ }
+
+ String getStatusText(BuildContext context) {
+ String statusText = "";
+ if (patientSickLeavesResponseModel.status == 1) {
+ statusText = LocaleKeys.pendingActivation.tr(context: context);
+ } else if (patientSickLeavesResponseModel.status == 2) {
+ statusText = LocaleKeys.ready.tr(context: context);
+ } else if (patientSickLeavesResponseModel.status == 3) {
+ statusText = LocaleKeys.awaitingApproval.tr(context: context);
+ } else {
+ statusText = "";
+ }
+ return statusText;
+ }
+
+ Color getStatusColor() {
+ Color statusColor = Colors.white;
+ if (patientSickLeavesResponseModel.status == 1) {
+ statusColor = Color(0xffCC9B14);
+ } else if (patientSickLeavesResponseModel.status == 2) {
+ statusColor = Color(0xff359846);
+ } else if (patientSickLeavesResponseModel.status == 3) {
+ statusColor = Color(0xffD02127);
+ } else {
+ statusColor = Colors.white;
+ }
+ return statusColor;
+ }
+}
diff --git a/lib/presentation/prescriptions/prescription_detail_page.dart b/lib/presentation/prescriptions/prescription_detail_page.dart
index 8f17c54..b3ace3d 100644
--- a/lib/presentation/prescriptions/prescription_detail_page.dart
+++ b/lib/presentation/prescriptions/prescription_detail_page.dart
@@ -13,6 +13,7 @@ import 'package:hmg_patient_app_new/extensions/widget_extensions.dart';
import 'package:hmg_patient_app_new/features/prescriptions/models/resp_models/patient_prescriptions_response_model.dart';
import 'package:hmg_patient_app_new/features/prescriptions/prescriptions_view_model.dart';
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
+import 'package:hmg_patient_app_new/presentation/lab/collapsing_list_view.dart';
import 'package:hmg_patient_app_new/presentation/prescriptions/prescription_item_view.dart';
import 'package:hmg_patient_app_new/presentation/prescriptions/prescription_reminder_view.dart';
import 'package:hmg_patient_app_new/theme/colors.dart';
@@ -53,94 +54,91 @@ class _PrescriptionDetailPageState extends State {
prescriptionsViewModel = Provider.of(context, listen: false);
return Scaffold(
backgroundColor: AppColors.bgScaffoldColor,
- appBar: AppBar(
- title: LocaleKeys.prescriptions.tr(context: context).toText18(),
- backgroundColor: AppColors.bgScaffoldColor,
- ),
body: Column(
children: [
Expanded(
- child: SingleChildScrollView(
- child: Consumer(builder: (context, prescriptionVM, child) {
- return Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- LocaleKeys.prescriptions.tr(context: context).toText24(isBold: true).paddingSymmetrical(24.h, 0.h),
- SizedBox(height: 24.h),
- Container(
- decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
- color: AppColors.whiteColor,
- borderRadius: 20.h,
- hasShadow: true,
- ),
- child: Padding(
- padding: EdgeInsets.all(16.h),
- child: Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- Row(
- mainAxisSize: MainAxisSize.min,
- children: [
- Image.network(
- widget.prescriptionsResponseModel.doctorImageURL!,
- width: 24.h,
- height: 24.h,
- fit: BoxFit.fill,
- ).circle(100),
- SizedBox(width: 8.h),
- Expanded(child: widget.prescriptionsResponseModel.doctorName!.toText16(isBold: true)),
- ],
- ),
- SizedBox(height: 16.h),
- Wrap(
- direction: Axis.horizontal,
- spacing: 4.h,
- runSpacing: -8.h,
- children: [
- AppCustomChipWidget(
- icon: AppAssets.doctor_calendar_icon,
- labelText: DateUtil.formatDateToDate(DateUtil.convertStringToDate(widget.prescriptionsResponseModel.appointmentDate), false),
- ),
- AppCustomChipWidget(
- labelText: widget.prescriptionsResponseModel.clinicDescription!,
- ),
- AppCustomChipWidget(
- icon: AppAssets.rating_icon,
- iconColor: AppColors.ratingColorYellow,
- labelText: "Rating: ${widget.prescriptionsResponseModel.decimalDoctorRate}".needTranslation,
- ),
- AppCustomChipWidget(
- labelText: widget.prescriptionsResponseModel.name!,
- ),
- ],
- ),
- ],
+ child: CollapsingListView(
+ title: LocaleKeys.prescriptions.tr(context: context),
+ child: SingleChildScrollView(
+ child: Consumer(builder: (context, prescriptionVM, child) {
+ return Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ SizedBox(height: 24.h),
+ Container(
+ decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
+ color: AppColors.whiteColor,
+ borderRadius: 20.h,
+ hasShadow: true,
+ ),
+ child: Padding(
+ padding: EdgeInsets.all(16.h),
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Row(
+ mainAxisSize: MainAxisSize.min,
+ children: [
+ Image.network(
+ widget.prescriptionsResponseModel.doctorImageURL!,
+ width: 24.h,
+ height: 24.h,
+ fit: BoxFit.fill,
+ ).circle(100),
+ SizedBox(width: 8.h),
+ Expanded(child: widget.prescriptionsResponseModel.doctorName!.toText16(isBold: true)),
+ ],
+ ),
+ SizedBox(height: 16.h),
+ Wrap(
+ direction: Axis.horizontal,
+ spacing: 4.h,
+ runSpacing: 4.h,
+ children: [
+ AppCustomChipWidget(
+ icon: AppAssets.doctor_calendar_icon,
+ labelText: DateUtil.formatDateToDate(DateUtil.convertStringToDate(widget.prescriptionsResponseModel.appointmentDate), false),
+ ),
+ AppCustomChipWidget(
+ labelText: widget.prescriptionsResponseModel.clinicDescription!,
+ ),
+ AppCustomChipWidget(
+ icon: AppAssets.rating_icon,
+ iconColor: AppColors.ratingColorYellow,
+ labelText: "Rating: ${widget.prescriptionsResponseModel.decimalDoctorRate}".needTranslation,
+ ),
+ AppCustomChipWidget(
+ labelText: widget.prescriptionsResponseModel.name!,
+ ),
+ ],
+ ),
+ ],
+ ),
),
- ),
- ).paddingSymmetrical(24.h, 0.h),
- SizedBox(height: 16.h),
- ListView.builder(
- shrinkWrap: true,
- physics: NeverScrollableScrollPhysics(),
- itemCount: prescriptionVM.isPrescriptionsDetailsLoading ? 5 : prescriptionVM.prescriptionDetailsList.length,
- itemBuilder: (context, index) {
- return prescriptionVM.isPrescriptionsDetailsLoading
- ? PrescriptionItemView(prescriptionVM: prescriptionVM, index: index, isLoading: true)
- : AnimationConfiguration.staggeredList(
- position: index,
- duration: const Duration(milliseconds: 500),
- child: SlideAnimation(
- verticalOffset: 100.0,
- child: FadeInAnimation(
- child: PrescriptionItemView(prescriptionVM: prescriptionVM, index: index),
+ ).paddingSymmetrical(24.h, 0.h),
+ ListView.builder(
+ shrinkWrap: true,
+ physics: NeverScrollableScrollPhysics(),
+ itemCount: prescriptionVM.isPrescriptionsDetailsLoading ? 5 : prescriptionVM.prescriptionDetailsList.length,
+ itemBuilder: (context, index) {
+ return prescriptionVM.isPrescriptionsDetailsLoading
+ ? PrescriptionItemView(prescriptionVM: prescriptionVM, index: index, isLoading: true)
+ : AnimationConfiguration.staggeredList(
+ position: index,
+ duration: const Duration(milliseconds: 500),
+ child: SlideAnimation(
+ verticalOffset: 100.0,
+ child: FadeInAnimation(
+ child: PrescriptionItemView(prescriptionVM: prescriptionVM, index: index),
+ ),
),
- ),
- );
- },
- ).paddingSymmetrical(24.h, 0.h),
- ],
- );
- }),
+ );
+ },
+ ).paddingSymmetrical(24.h, 0.h),
+ ],
+ );
+ }),
+ ),
),
),
Container(
diff --git a/lib/presentation/prescriptions/prescriptions_list_page.dart b/lib/presentation/prescriptions/prescriptions_list_page.dart
index 9574f28..148afb1 100644
--- a/lib/presentation/prescriptions/prescriptions_list_page.dart
+++ b/lib/presentation/prescriptions/prescriptions_list_page.dart
@@ -11,6 +11,7 @@ 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/prescriptions/prescriptions_view_model.dart';
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
+import 'package:hmg_patient_app_new/presentation/lab/collapsing_list_view.dart';
import 'package:hmg_patient_app_new/presentation/prescriptions/prescription_detail_page.dart';
import 'package:hmg_patient_app_new/theme/colors.dart';
import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart';
@@ -43,256 +44,252 @@ class _PrescriptionsListPageState extends State {
prescriptionsViewModel = Provider.of(context, listen: false);
return Scaffold(
backgroundColor: AppColors.bgScaffoldColor,
- appBar: AppBar(
- title: LocaleKeys.prescriptions.tr(context: context).toText18(),
- backgroundColor: AppColors.bgScaffoldColor,
- ),
- body: SingleChildScrollView(
- child: Consumer