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/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/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_consts.dart b/lib/core/api_consts.dart
index 42f10f4..bad2e4c 100644
--- a/lib/core/api_consts.dart
+++ b/lib/core/api_consts.dart
@@ -726,7 +726,7 @@ const DEACTIVATE_ACCOUNT = 'Services/Patients.svc/REST/PatientAppleActivation_In
class ApiConsts {
static const maxSmallScreen = 660;
- static AppEnvironmentTypeEnum appEnvironmentType = AppEnvironmentTypeEnum.uat;
+ static AppEnvironmentTypeEnum appEnvironmentType = AppEnvironmentTypeEnum.prod;
// static String baseUrl = 'https://uat.hmgwebservices.com/'; // HIS API URL UAT
diff --git a/lib/core/app_assets.dart b/lib/core/app_assets.dart
index 23945d0..106a5ad 100644
--- a/lib/core/app_assets.dart
+++ b/lib/core/app_assets.dart
@@ -100,6 +100,12 @@ class AppAssets {
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/dependencies.dart b/lib/core/dependencies.dart
index 0edec4e..f86ec97 100644
--- a/lib/core/dependencies.dart
+++ b/lib/core/dependencies.dart
@@ -6,13 +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/models/habib_wallet_repo.dart';
-import 'package:hmg_patient_app_new/features/habib_wallet/models/habib_wallet_view_model.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';
@@ -88,6 +91,7 @@ class AppDependencies {
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
@@ -141,6 +145,27 @@ class AppDependencies {
),
);
+ getIt.registerLazySingleton(
+ () => HabibWalletViewModel(
+ habibWalletRepo: getIt(),
+ errorHandlerService: getIt(),
+ ),
+ );
+
+ getIt.registerLazySingleton(
+ () => MedicalFileViewModel(
+ medicalFileRepo: getIt(),
+ errorHandlerService: getIt(),
+ ),
+ );
+
+ getIt.registerLazySingleton(
+ () => BookAppointmentsViewModel(
+ bookAppointmentsRepo: getIt(),
+ errorHandlerService: getIt(),
+ ),
+ );
+
getIt.registerLazySingleton(
() => AuthenticationViewModel(
authenticationRepo: getIt(), cacheService: getIt(), navigationService: getIt(), dialogService: getIt(), appState: getIt(), errorHandlerService: getIt(), localAuthService: getIt()),
diff --git a/lib/core/utils/utils.dart b/lib/core/utils/utils.dart
index a330879..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) {
@@ -629,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/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/models/habib_wallet_repo.dart b/lib/features/habib_wallet/habib_wallet_repo.dart
similarity index 100%
rename from lib/features/habib_wallet/models/habib_wallet_repo.dart
rename to lib/features/habib_wallet/habib_wallet_repo.dart
diff --git a/lib/features/habib_wallet/models/habib_wallet_view_model.dart b/lib/features/habib_wallet/habib_wallet_view_model.dart
similarity index 93%
rename from lib/features/habib_wallet/models/habib_wallet_view_model.dart
rename to lib/features/habib_wallet/habib_wallet_view_model.dart
index 64c6ddf..8e4fc26 100644
--- a/lib/features/habib_wallet/models/habib_wallet_view_model.dart
+++ b/lib/features/habib_wallet/habib_wallet_view_model.dart
@@ -1,5 +1,5 @@
import 'package:flutter/material.dart';
-import 'package:hmg_patient_app_new/features/habib_wallet/models/habib_wallet_repo.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 {
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 a5528cf..2035f30 100644
--- a/lib/features/my_appointments/my_appointments_repo.dart
+++ b/lib/features/my_appointments/my_appointments_repo.dart
@@ -34,6 +34,8 @@ abstract class MyAppointmentsRepo {
{required PatientAppointmentHistoryResponseModel patientAppointmentHistoryResponseModel, required String scannedCode, required int checkInType});
Future>>> getPatientAppointmentsForTimeLine();
+
+ Future>>> getPatientDoctorsList();
}
class MyAppointmentsRepoImp implements MyAppointmentsRepo {
@@ -444,4 +446,49 @@ class MyAppointmentsRepoImp implements MyAppointmentsRepo {
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 d3121af..c6d3499 100644
--- a/lib/features/my_appointments/my_appointments_view_model.dart
+++ b/lib/features/my_appointments/my_appointments_view_model.dart
@@ -13,6 +13,7 @@ class MyAppointmentsViewModel extends ChangeNotifier {
bool isMyAppointmentsLoading = false;
bool isAppointmentPatientShareLoading = false;
bool isTimeLineAppointmentsLoading = false;
+ bool isPatientMyDoctorsLoading = false;
List patientAppointmentsHistoryList = [];
@@ -21,6 +22,8 @@ class MyAppointmentsViewModel extends ChangeNotifier {
List patientTimelineAppointmentsList = [];
+ List patientMyDoctorsList = [];
+
PatientAppointmentShareResponseModel? patientAppointmentShareResponseModel;
MyAppointmentsViewModel({required this.myAppointmentsRepo, required this.errorHandlerService});
@@ -35,9 +38,11 @@ class MyAppointmentsViewModel extends ChangeNotifier {
patientUpcomingAppointmentsHistoryList.clear();
patientArrivedAppointmentsHistoryList.clear();
patientTimelineAppointmentsList.clear();
+ patientMyDoctorsList.clear();
isMyAppointmentsLoading = true;
isAppointmentPatientShareLoading = true;
isTimeLineAppointmentsLoading = true;
+ isPatientMyDoctorsLoading = true;
notifyListeners();
}
@@ -56,6 +61,11 @@ class MyAppointmentsViewModel extends ChangeNotifier {
notifyListeners();
}
+ setIsPatientMyDoctorsLoading(bool val) {
+ isPatientMyDoctorsLoading = val;
+ notifyListeners();
+ }
+
setAppointmentReminder(bool value, PatientAppointmentHistoryResponseModel item) {
int index = patientAppointmentsHistoryList.indexOf(item);
if (index != -1) {
@@ -263,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/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 2739a6b..901c529 100644
--- a/lib/main.dart
+++ b/lib/main.dart
@@ -9,7 +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/habib_wallet/models/habib_wallet_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 +97,10 @@ void main() async {
),
),
ChangeNotifierProvider(
- create: (_) => MedicalFileViewModel(),
+ create: (_) => MedicalFileViewModel(
+ medicalFileRepo: getIt(),
+ errorHandlerService: getIt(),
+ ),
),
ChangeNotifierProvider(
create: (_) => MyAppointmentsViewModel(
@@ -116,6 +120,12 @@ void main() async {
errorHandlerService: getIt(),
),
),
+ ChangeNotifierProvider(
+ create: (_) => BookAppointmentsViewModel(
+ bookAppointmentsRepo: getIt(),
+ errorHandlerService: getIt(),
+ ),
+ ),
ChangeNotifierProvider(
create: (_) => AuthenticationViewModel(
authenticationRepo: getIt(),
diff --git a/lib/presentation/appointments/appointment_payment_page.dart b/lib/presentation/appointments/appointment_payment_page.dart
index baa2af3..a617647 100644
--- a/lib/presentation/appointments/appointment_payment_page.dart
+++ b/lib/presentation/appointments/appointment_payment_page.dart
@@ -370,7 +370,7 @@ class _AppointmentPaymentPageState extends State {
onSuccess: (value) async {
print(value);
await myAppointmentsViewModel.addAdvanceNumberRequest(
- advanceNumber: Utils.isVidaPlusProject(appState, widget.patientAppointmentHistoryResponseModel.projectID)
+ advanceNumber: Utils.isVidaPlusProject(widget.patientAppointmentHistoryResponseModel.projectID)
? value.data['OnlineCheckInAppointments'][0]['AdvanceNumber_VP'].toString()
: value.data['OnlineCheckInAppointments'][0]['AdvanceNumber'].toString(),
paymentReference: payfortViewModel.payfortCheckPaymentStatusResponseModel!.fortId!,
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/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
index 632b11d..1d24d05 100644
--- a/lib/presentation/habib_wallet/habib_wallet_page.dart
+++ b/lib/presentation/habib_wallet/habib_wallet_page.dart
@@ -7,7 +7,7 @@ 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/models/habib_wallet_view_model.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';
diff --git a/lib/presentation/home/landing_page.dart b/lib/presentation/home/landing_page.dart
index b63b404..26e5147 100644
--- a/lib/presentation/home/landing_page.dart
+++ b/lib/presentation/home/landing_page.dart
@@ -12,7 +12,7 @@ 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/models/habib_wallet_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';
@@ -64,6 +64,7 @@ class _LandingPageState extends State {
habibWalletVM.getPatientBalanceAmount();
myAppointmentsViewModel.initAppointmentsViewModel();
myAppointmentsViewModel.getPatientAppointments(true, false);
+ myAppointmentsViewModel.getPatientMyDoctors();
prescriptionsViewModel.initPrescriptionsViewModel();
}
});
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 9bb53f5..3509000 100644
--- a/lib/presentation/home/widgets/habib_wallet_card.dart
+++ b/lib/presentation/home/widgets/habib_wallet_card.dart
@@ -4,7 +4,7 @@ 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/models/habib_wallet_view_model.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';
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/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 4860bb1..48193e8 100644
--- a/lib/presentation/medical_file/medical_file_page.dart
+++ b/lib/presentation/medical_file/medical_file_page.dart
@@ -13,23 +13,33 @@ 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 {
@@ -43,6 +53,7 @@ class _MedicalFilePageState extends State {
late InsuranceViewModel insuranceViewModel;
late AppState appState;
late MyAppointmentsViewModel myAppointmentsViewModel;
+ late MedicalFileViewModel medicalFileViewModel;
int currentIndex = 0;
@@ -50,6 +61,8 @@ class _MedicalFilePageState extends State {
void initState() {
scheduleMicrotask(() {
insuranceViewModel.initInsuranceProvider();
+ medicalFileViewModel.setIsPatientSickLeaveListLoading(true);
+ medicalFileViewModel.getPatientSickLeaveList();
});
super.initState();
}
@@ -58,16 +71,17 @@ class _MedicalFilePageState extends State {
Widget build(BuildContext 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,
- body: SingleChildScrollView(
- child: Padding(
- padding: EdgeInsets.only(top: 80.0),
+ body: CollapsingListView(
+ title: LocaleKeys.medicalFile.tr(context: context),
+ isLeading: false,
+ child: 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),
@@ -318,116 +332,257 @@ class _MedicalFilePageState extends State {
SizedBox(height: 16.h),
Consumer(builder: (context, prescriptionVM, child) {
return prescriptionVM.isPrescriptionsOrdersLoading
- ? 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.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: [
- Utils.buildSvgWithAssets(
- icon: AppAssets.prescription_item_icon,
- width: 40.h,
- height: 40.h,
- ),
- SizedBox(width: 8.h),
- Row(
- mainAxisSize: MainAxisSize.max,
+ ? 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: [
- 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,
+ 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,
),
),
- ),
- );
- },
- 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(
+ 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: 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,
- ),
+ child: ("Dr. John Smith Smith Smith").toString().toText12(fontWeight: FontWeight.w500, isCenter: true, maxLine: 2).toShimmer2(isShow: true),
),
],
),
- ],
- ),
- ),
- ).paddingSymmetrical(24.h, 0.h);
+ )
+ : 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:
@@ -448,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/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/services/error_handler_service.dart b/lib/services/error_handler_service.dart
index 59a0205..092cf38 100644
--- a/lib/services/error_handler_service.dart
+++ b/lib/services/error_handler_service.dart
@@ -47,7 +47,7 @@ class ErrorHandlerServiceImp implements ErrorHandlerService {
} else {
loggerService.errorLogs("Unhandled failure type: $failure");
- await _showDialog(failure, title: "Error");
+ await _showDialog(failure, title: "Error", onOkPressed: onOkPressed);
}
}
diff --git a/pubspec.yaml b/pubspec.yaml
index 36326f4..147d7ac 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -76,6 +76,8 @@ dependencies:
flutter_nfc_kit: ^3.6.0
barcode_scan2: ^4.5.1
keyboard_actions: ^4.2.0
+ path_provider: ^2.0.8
+ open_filex: ^4.7.0
dev_dependencies:
flutter_test: