request medical report implementation contd.

pull/67/head
Haroon Amjad 1 month ago
parent 2de02102c2
commit 8bb0e495cc

@ -727,7 +727,7 @@ const FAMILY_FILES= 'Services/Authentication.svc/REST/GetAllSharedRecordsByStatu
class ApiConsts { class ApiConsts {
static const maxSmallScreen = 660; static const maxSmallScreen = 660;
static AppEnvironmentTypeEnum appEnvironmentType = AppEnvironmentTypeEnum.prod; static AppEnvironmentTypeEnum appEnvironmentType = AppEnvironmentTypeEnum.uat;
// static String baseUrl = 'https://uat.hmgwebservices.com/'; // HIS API URL UAT // static String baseUrl = 'https://uat.hmgwebservices.com/'; // HIS API URL UAT

@ -11,7 +11,7 @@ import 'package:hmg_patient_app_new/services/logger_service.dart';
abstract class InsuranceRepo { abstract class InsuranceRepo {
Future<Either<Failure, GenericApiModel<List<PatientInsuranceDetailsResponseModel>>>> getPatientInsuranceDetails(); Future<Either<Failure, GenericApiModel<List<PatientInsuranceDetailsResponseModel>>>> getPatientInsuranceDetails();
Future<Either<Failure, GenericApiModel<List<PatientInsuranceCardHistoryResponseModel>>>> getPatientInsuranceCardHistory({required String patientId}); Future<Either<Failure, GenericApiModel<List<PatientInsuranceCardHistoryResponseModel>>>> getPatientInsuranceCardHistory();
Future<Either<Failure, GenericApiModel<PatientInsuranceUpdateResponseModel>>> getPatientInsuranceDetailsForUpdate({required String patientId, required String identificationNo}); Future<Either<Failure, GenericApiModel<PatientInsuranceUpdateResponseModel>>> getPatientInsuranceDetailsForUpdate({required String patientId, required String identificationNo});
} }
@ -64,7 +64,7 @@ class InsuranceRepoImp implements InsuranceRepo {
} }
@override @override
Future<Either<Failure, GenericApiModel<List<PatientInsuranceCardHistoryResponseModel>>>> getPatientInsuranceCardHistory({required String patientId}) async { Future<Either<Failure, GenericApiModel<List<PatientInsuranceCardHistoryResponseModel>>>> getPatientInsuranceCardHistory() async {
Map<String, dynamic> mapDevice = {}; Map<String, dynamic> mapDevice = {};
try { try {

@ -66,6 +66,7 @@ class InsuranceViewModel extends ChangeNotifier {
// (failure) async => await errorHandlerService.handleError(failure: failure), // (failure) async => await errorHandlerService.handleError(failure: failure),
(failure) async { (failure) async {
isInsuranceLoading = false; isInsuranceLoading = false;
notifyListeners();
}, },
(apiResponse) { (apiResponse) {
if (apiResponse.messageStatus == 2) { if (apiResponse.messageStatus == 2) {
@ -84,10 +85,13 @@ class InsuranceViewModel extends ChangeNotifier {
} }
Future<void> getPatientInsuranceCardHistory({Function(dynamic)? onSuccess, Function(String)? onError}) async { Future<void> getPatientInsuranceCardHistory({Function(dynamic)? onSuccess, Function(String)? onError}) async {
final result = await insuranceRepo.getPatientInsuranceCardHistory(patientId: "1231755"); final result = await insuranceRepo.getPatientInsuranceCardHistory();
result.fold( result.fold(
(failure) async => await errorHandlerService.handleError(failure: failure), (failure) async {
isInsuranceHistoryLoading = false;
notifyListeners();
},
(apiResponse) { (apiResponse) {
if (apiResponse.messageStatus == 2) { if (apiResponse.messageStatus == 2) {
// dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {}); // dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {});
@ -108,7 +112,10 @@ class InsuranceViewModel extends ChangeNotifier {
final result = await insuranceRepo.getPatientInsuranceDetailsForUpdate(patientId: patientID, identificationNo: identificationNo); final result = await insuranceRepo.getPatientInsuranceDetailsForUpdate(patientId: patientID, identificationNo: identificationNo);
result.fold( result.fold(
(failure) async => await errorHandlerService.handleError(failure: failure), (failure) async {
isInsuranceUpdateDetailsLoading = false;
notifyListeners();
},
(apiResponse) { (apiResponse) {
if (apiResponse.messageStatus == 2) { if (apiResponse.messageStatus == 2) {
// dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {}); // dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {});

@ -8,6 +8,7 @@ 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_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_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/features/medical_file/models/patient_vaccine_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/services/logger_service.dart'; import 'package:hmg_patient_app_new/services/logger_service.dart';
import '../authentication/models/resp_models/authenticated_user_resp_model.dart'; import '../authentication/models/resp_models/authenticated_user_resp_model.dart';
@ -27,6 +28,8 @@ abstract class MedicalFileRepo {
Future<Either<Failure, GenericApiModel<List<FamilyFileResponseModelLists>>>> getPatientFamilyFiles(); Future<Either<Failure, GenericApiModel<List<FamilyFileResponseModelLists>>>> getPatientFamilyFiles();
Future<Either<Failure, GenericApiModel<List<dynamic>>>> addFamilyFile({required dynamic request}); Future<Either<Failure, GenericApiModel<List<dynamic>>>> addFamilyFile({required dynamic request});
Future<Either<Failure, GenericApiModel<List<PatientAppointmentHistoryResponseModel>>>> getPatientAppointmentsForMedicalReport();
} }
class MedicalFileRepoImp implements MedicalFileRepo { class MedicalFileRepoImp implements MedicalFileRepo {
@ -348,4 +351,51 @@ class MedicalFileRepoImp implements MedicalFileRepo {
return Left(UnknownFailure(e.toString())); return Left(UnknownFailure(e.toString()));
} }
} }
@override
Future<Either<Failure, GenericApiModel<List<PatientAppointmentHistoryResponseModel>>>> getPatientAppointmentsForMedicalReport() async {
Map<String, dynamic> mapDevice = {
"IsActiveAppointment": false,
"IsComingFromCOC": false,
"isForUpcomming": false,
"IsForMedicalReport": true,
"IsForArrived": false,
};
try {
GenericApiModel<List<PatientAppointmentHistoryResponseModel>>? apiResponse;
Failure? failure;
await apiClient.post(
GET_PATIENT_APPOINTMENT_HISTORY,
body: mapDevice,
onFailure: (error, statusCode, {messageStatus, failureType}) {
failure = failureType;
},
onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
try {
final list = response['AppoimentAllHistoryResultList'];
// if (list == null || list.isEmpty) {
// throw Exception("Appointments list is empty");
// }
final appointmentsList = list.map((item) => PatientAppointmentHistoryResponseModel.fromJson(item as Map<String, dynamic>)).toList().cast<PatientAppointmentHistoryResponseModel>();
apiResponse = GenericApiModel<List<PatientAppointmentHistoryResponseModel>>(
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()));
}
}
} }

@ -8,6 +8,7 @@ import 'package:hmg_patient_app_new/features/medical_file/models/family_file_res
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_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_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/features/medical_file/models/patient_vaccine_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/services/dialog_service.dart'; import 'package:hmg_patient_app_new/services/dialog_service.dart';
import 'package:hmg_patient_app_new/services/error_handler_service.dart'; import 'package:hmg_patient_app_new/services/error_handler_service.dart';
@ -30,6 +31,9 @@ class MedicalFileViewModel extends ChangeNotifier {
List<PatientMedicalReportResponseModel> patientMedicalReportReadyList = []; List<PatientMedicalReportResponseModel> patientMedicalReportReadyList = [];
List<PatientMedicalReportResponseModel> patientMedicalReportCancelledList = []; List<PatientMedicalReportResponseModel> patientMedicalReportCancelledList = [];
List<PatientAppointmentHistoryResponseModel> patientMedicalReportAppointmentHistoryList = [];
PatientAppointmentHistoryResponseModel? patientMedicalReportSelectedAppointment;
List<FamilyFileResponseModelLists> patientFamilyFiles = []; List<FamilyFileResponseModelLists> patientFamilyFiles = [];
String patientSickLeavePDFBase64 = ""; String patientSickLeavePDFBase64 = "";
@ -42,6 +46,7 @@ class MedicalFileViewModel extends ChangeNotifier {
MedicalFileViewModel({required this.medicalFileRepo, required this.errorHandlerService}); MedicalFileViewModel({required this.medicalFileRepo, required this.errorHandlerService});
initMedicalFileProvider() { initMedicalFileProvider() {
patientMedicalReportAppointmentHistoryList.clear();
isPatientVaccineListLoading = true; isPatientVaccineListLoading = true;
isPatientMedicalReportsListLoading = true; isPatientMedicalReportsListLoading = true;
notifyListeners(); notifyListeners();
@ -87,6 +92,11 @@ class MedicalFileViewModel extends ChangeNotifier {
notifyListeners(); notifyListeners();
} }
setSelectedMedicalReportAppointment(PatientAppointmentHistoryResponseModel? val) {
patientMedicalReportSelectedAppointment = val;
notifyListeners();
}
void onTabChanged(int index) { void onTabChanged(int index) {
selectedTabIndex = index; selectedTabIndex = index;
notifyListeners(); notifyListeners();
@ -293,9 +303,32 @@ class MedicalFileViewModel extends ChangeNotifier {
); );
} }
Future<void> getPatientMedicalReportAppointmentsList({Function(dynamic)? onSuccess, Function(String)? onError}) async {
patientMedicalReportAppointmentHistoryList.clear();
notifyListeners();
final result = await medicalFileRepo.getPatientAppointmentsForMedicalReport();
result.fold(
(failure) async {
onError!(failure.message);
},
(apiResponse) {
if (apiResponse.messageStatus == 2) {
// dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {});
} else if (apiResponse.messageStatus == 1) {
patientMedicalReportAppointmentHistoryList = apiResponse.data!;
notifyListeners();
if (onSuccess != null) {
onSuccess(apiResponse);
}
}
},
);
}
Future<void> addFamilyFile() async { Future<void> addFamilyFile() async {
final resultEither = await medicalFileRepo.addFamilyFile(request: {}); final resultEither = await medicalFileRepo.addFamilyFile(request: {});
resultEither.fold((failure) async => await errorHandlerService.handleError(failure: failure), (apiResponse) async {}); resultEither.fold((failure) async => await errorHandlerService.handleError(failure: failure), (apiResponse) async {});
} }
} }

@ -56,13 +56,10 @@ class MyAppointmentsRepoImp implements MyAppointmentsRepo {
Future<Either<Failure, GenericApiModel<List<PatientAppointmentHistoryResponseModel>>>> getPatientAppointments({required bool isActiveAppointment, required bool isArrivedAppointments}) async { Future<Either<Failure, GenericApiModel<List<PatientAppointmentHistoryResponseModel>>>> getPatientAppointments({required bool isActiveAppointment, required bool isArrivedAppointments}) async {
Map<String, dynamic> mapDevice = { Map<String, dynamic> mapDevice = {
"IsActiveAppointment": isActiveAppointment, "IsActiveAppointment": isActiveAppointment,
"isDentalAllowedBackend": false,
"PatientTypeID": 1,
"IsComingFromCOC": false, "IsComingFromCOC": false,
"PatientType": 1,
"isForUpcomming": false, "isForUpcomming": false,
"IsForMedicalReport": false,
"IsForArrived": isArrivedAppointments, "IsForArrived": isArrivedAppointments,
"PatientOutSA": 0
}; };
try { try {

@ -8,6 +8,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/core/utils/utils.dart';
import 'package:hmg_patient_app_new/extensions/string_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/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/my_appointments/models/resp_models/patient_appointment_history_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/my_appointments/my_appointments_view_model.dart';
import 'package:hmg_patient_app_new/features/my_appointments/utils/appointment_type.dart'; import 'package:hmg_patient_app_new/features/my_appointments/utils/appointment_type.dart';
@ -21,12 +22,21 @@ import 'package:hmg_patient_app_new/widgets/transitions/fade_page.dart';
import 'package:smooth_corner/smooth_corner.dart'; import 'package:smooth_corner/smooth_corner.dart';
class AppointmentCard extends StatefulWidget { class AppointmentCard extends StatefulWidget {
AppointmentCard({super.key, required this.patientAppointmentHistoryResponseModel, required this.myAppointmentsViewModel, this.isLoading = false, this.isFromHomePage = false}); AppointmentCard(
{super.key,
required this.patientAppointmentHistoryResponseModel,
required this.myAppointmentsViewModel,
this.isLoading = false,
this.isFromHomePage = false,
this.isFromMedicalReport = false,
this.medicalFileViewModel});
PatientAppointmentHistoryResponseModel patientAppointmentHistoryResponseModel; PatientAppointmentHistoryResponseModel patientAppointmentHistoryResponseModel;
MyAppointmentsViewModel myAppointmentsViewModel; MyAppointmentsViewModel myAppointmentsViewModel;
bool isLoading; bool isLoading;
bool isFromHomePage; bool isFromHomePage;
bool isFromMedicalReport;
MedicalFileViewModel? medicalFileViewModel;
@override @override
State<AppointmentCard> createState() => _AppointmentCardState(); State<AppointmentCard> createState() => _AppointmentCardState();
@ -171,75 +181,94 @@ class _AppointmentCardState extends State<AppointmentCard> {
], ],
), ),
SizedBox(height: 16.h), SizedBox(height: 16.h),
Row( widget.isFromMedicalReport
children: [ ? CustomButton(
Expanded( text: "Select appointment".needTranslation,
flex: 6, onPressed: () {
child: AppointmentType.isArrived(widget.patientAppointmentHistoryResponseModel) widget.medicalFileViewModel!.setSelectedMedicalReportAppointment(widget.patientAppointmentHistoryResponseModel);
? getArrivedAppointmentButton().toShimmer2(isShow: widget.isLoading) Navigator.pop(context, false);
: CustomButton( },
text: AppointmentType.getNextActionText(widget.patientAppointmentHistoryResponseModel.nextAction), backgroundColor: AppColors.secondaryLightRedColor,
onPressed: () { borderColor: AppColors.secondaryLightRedColor,
Navigator.of(context) textColor: AppColors.primaryRedColor,
.push(CustomPageRoute( fontSize: 14,
page: AppointmentDetailsPage(patientAppointmentHistoryResponseModel: widget.patientAppointmentHistoryResponseModel), fontWeight: FontWeight.w500,
)) borderRadius: 12,
.then((val) { padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
widget.myAppointmentsViewModel.initAppointmentsViewModel();
widget.myAppointmentsViewModel.getPatientAppointments(true, false);
});
},
backgroundColor: AppointmentType.getNextActionButtonColor(widget.patientAppointmentHistoryResponseModel.nextAction).withOpacity(0.15),
borderColor: AppointmentType.getNextActionButtonColor(widget.patientAppointmentHistoryResponseModel.nextAction).withOpacity(0.01),
textColor: AppointmentType.getNextActionTextColor(widget.patientAppointmentHistoryResponseModel.nextAction),
fontSize: 14,
fontWeight: FontWeight.w500,
borderRadius: 12,
padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
height: 40.h,
icon: AppointmentType.getNextActionIcon(widget.patientAppointmentHistoryResponseModel.nextAction),
iconColor: AppointmentType.getNextActionTextColor(widget.patientAppointmentHistoryResponseModel.nextAction),
iconSize: 15.h,
).toShimmer2(isShow: widget.isLoading),
),
SizedBox(width: 8.h),
Expanded(
flex: 1,
child: Container(
height: 40.h, height: 40.h,
width: 40.h, icon: AppAssets.checkmark_icon,
decoration: RoundedRectangleBorder().toSmoothCornerDecoration( iconColor: AppColors.primaryRedColor,
color: AppColors.textColor, iconSize: 16.h,
borderRadius: 10.h, )
), : Row(
child: Padding( children: [
padding: EdgeInsets.all(10.h), Expanded(
child: Transform.flip( flex: 6,
flipX: appState.isArabic() ? true : false, child: AppointmentType.isArrived(widget.patientAppointmentHistoryResponseModel)
child: Utils.buildSvgWithAssets( ? getArrivedAppointmentButton().toShimmer2(isShow: widget.isLoading)
icon: AppAssets.forward_arrow_icon, : CustomButton(
iconColor: AppColors.whiteColor, text: AppointmentType.getNextActionText(widget.patientAppointmentHistoryResponseModel.nextAction),
width: 10.h, onPressed: () {
height: 10.h, Navigator.of(context)
fit: BoxFit.contain, .push(CustomPageRoute(
), page: AppointmentDetailsPage(patientAppointmentHistoryResponseModel: widget.patientAppointmentHistoryResponseModel),
))
.then((val) {
widget.myAppointmentsViewModel.initAppointmentsViewModel();
widget.myAppointmentsViewModel.getPatientAppointments(true, false);
});
},
backgroundColor: AppointmentType.getNextActionButtonColor(widget.patientAppointmentHistoryResponseModel.nextAction).withOpacity(0.15),
borderColor: AppointmentType.getNextActionButtonColor(widget.patientAppointmentHistoryResponseModel.nextAction).withOpacity(0.01),
textColor: AppointmentType.getNextActionTextColor(widget.patientAppointmentHistoryResponseModel.nextAction),
fontSize: 14,
fontWeight: FontWeight.w500,
borderRadius: 12,
padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
height: 40.h,
icon: AppointmentType.getNextActionIcon(widget.patientAppointmentHistoryResponseModel.nextAction),
iconColor: AppointmentType.getNextActionTextColor(widget.patientAppointmentHistoryResponseModel.nextAction),
iconSize: 15.h,
).toShimmer2(isShow: widget.isLoading),
), ),
), SizedBox(width: 8.h),
).toShimmer2(isShow: widget.isLoading).onPress(() { Expanded(
Navigator.of(context) flex: 1,
.push( child: Container(
CustomPageRoute( height: 40.h,
page: AppointmentDetailsPage(patientAppointmentHistoryResponseModel: widget.patientAppointmentHistoryResponseModel), width: 40.h,
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.textColor,
borderRadius: 10.h,
),
child: Padding(
padding: EdgeInsets.all(10.h),
child: Transform.flip(
flipX: appState.isArabic() ? true : false,
child: Utils.buildSvgWithAssets(
icon: AppAssets.forward_arrow_icon,
iconColor: AppColors.whiteColor,
width: 10.h,
height: 10.h,
fit: BoxFit.contain,
),
),
),
).toShimmer2(isShow: widget.isLoading).onPress(() {
Navigator.of(context)
.push(
CustomPageRoute(
page: AppointmentDetailsPage(patientAppointmentHistoryResponseModel: widget.patientAppointmentHistoryResponseModel),
),
)
.then((val) {
widget.myAppointmentsViewModel.initAppointmentsViewModel();
widget.myAppointmentsViewModel.getPatientAppointments(true, false);
});
}),
), ),
) ],
.then((val) { ),
widget.myAppointmentsViewModel.initAppointmentsViewModel();
widget.myAppointmentsViewModel.getPatientAppointments(true, false);
});
}),
),
],
),
], ],
), ),
), ),

@ -3,12 +3,17 @@ import 'dart:async';
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:hmg_patient_app_new/core/app_assets.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/date_util.dart';
import 'package:hmg_patient_app_new/core/utils/size_utils.dart'; import 'package:hmg_patient_app_new/core/utils/size_utils.dart';
import 'package:hmg_patient_app_new/core/utils/utils.dart';
import 'package:hmg_patient_app_new/extensions/string_extensions.dart'; import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
import 'package:hmg_patient_app_new/features/insurance/insurance_view_model.dart'; import 'package:hmg_patient_app_new/features/insurance/insurance_view_model.dart';
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart'; import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
import 'package:hmg_patient_app_new/presentation/insurance/widgets/insurance_update_details_card.dart';
import 'package:hmg_patient_app_new/presentation/insurance/widgets/patient_insurance_card.dart'; import 'package:hmg_patient_app_new/presentation/insurance/widgets/patient_insurance_card.dart';
import 'package:hmg_patient_app_new/presentation/lab/lab_result_item_view.dart';
import 'package:hmg_patient_app_new/widgets/appbar/collapsing_list_view.dart'; import 'package:hmg_patient_app_new/widgets/appbar/collapsing_list_view.dart';
import 'package:hmg_patient_app_new/presentation/lab/search_lab_report.dart'; import 'package:hmg_patient_app_new/presentation/lab/search_lab_report.dart';
import 'package:hmg_patient_app_new/theme/colors.dart'; import 'package:hmg_patient_app_new/theme/colors.dart';
@ -30,6 +35,8 @@ class InsuranceHomePage extends StatefulWidget {
class _InsuranceHomePageState extends State<InsuranceHomePage> { class _InsuranceHomePageState extends State<InsuranceHomePage> {
late InsuranceViewModel insuranceViewModel; late InsuranceViewModel insuranceViewModel;
late AppState appState;
@override @override
void initState() { void initState() {
scheduleMicrotask(() { scheduleMicrotask(() {
@ -40,6 +47,7 @@ class _InsuranceHomePageState extends State<InsuranceHomePage> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
appState = getIt.get<AppState>();
insuranceViewModel = Provider.of<InsuranceViewModel>(context, listen: false); insuranceViewModel = Provider.of<InsuranceViewModel>(context, listen: false);
return Scaffold( return Scaffold(
backgroundColor: AppColors.bgScaffoldColor, backgroundColor: AppColors.bgScaffoldColor,
@ -48,44 +56,55 @@ class _InsuranceHomePageState extends State<InsuranceHomePage> {
history: () { history: () {
insuranceViewModel.setIsInsuranceHistoryLoading(true); insuranceViewModel.setIsInsuranceHistoryLoading(true);
insuranceViewModel.getPatientInsuranceCardHistory(); insuranceViewModel.getPatientInsuranceCardHistory();
showCommonBottomSheet(context, showCommonBottomSheetWithoutHeight(context, child: InsuranceHistory(), callBackFunc: () {}, title: "", isCloseButtonVisible: false, isFullScreen: false);
child: InsuranceHistory(), callBackFunc: (str) {}, title: "", height: ResponsiveExtension.screenHeight * 0.65, isCloseButtonVisible: false, isFullScreen: false);
}, },
child: SingleChildScrollView( child: SingleChildScrollView(
child: Consumer<InsuranceViewModel>(builder: (context, insuranceVM, child) { child: Consumer<InsuranceViewModel>(builder: (context, insuranceVM, child) {
return Column( return Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
// Row(
// mainAxisAlignment: MainAxisAlignment.spaceBetween,
// children: [
// "${LocaleKeys.insurance.tr(context: context)} ${LocaleKeys.updateInsurance.tr(context: context)}".toText24(isBold: true),
// CustomButton(
// icon: AppAssets.insurance_history_icon,
// iconColor: AppColors.primaryRedColor,
// iconSize: 21.h,
// text: LocaleKeys.history.tr(context: context),
// onPressed: () {
// },
// backgroundColor: AppColors.primaryRedColor.withOpacity(0.1),
// borderColor: AppColors.primaryRedColor.withOpacity(0.0),
// textColor: AppColors.primaryRedColor,
// fontSize: 14,
// fontWeight: FontWeight.w600,
// borderRadius: 12,
// padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
// height: 40.h,
// ),
// ],
// ).paddingSymmetrical(24.h, 24.h),
insuranceVM.isInsuranceLoading insuranceVM.isInsuranceLoading
? const MoviesShimmerWidget().paddingSymmetrical(24.h, 0) ? LabResultItemView(
: Padding( onTap: () {},
padding: EdgeInsets.only(top: 24.h), labOrder: null,
child: PatientInsuranceCard( index: 0,
insuranceCardDetailsModel: insuranceVM.patientInsuranceList.first, isLoading: true,
isInsuranceExpired: DateTime.now().isAfter(DateUtil.convertStringToDate(insuranceVM.patientInsuranceList.first.cardValidTo))), ).paddingSymmetrical(24.h, 24.h)
), : insuranceVM.patientInsuranceList.isNotEmpty
? Padding(
padding: EdgeInsets.only(top: 24.h),
child: PatientInsuranceCard(
insuranceCardDetailsModel: insuranceVM.patientInsuranceList.first,
isInsuranceExpired: DateTime.now().isAfter(DateUtil.convertStringToDate(insuranceVM.patientInsuranceList.first.cardValidTo))),
)
: Padding(
padding: EdgeInsets.only(top: MediaQuery.of(context).size.height * 0.12),
child: Utils.getNoDataWidget(
context,
noDataText: "You don't have insurance registered with HMG.".needTranslation,
callToActionButton: CustomButton(
icon: AppAssets.update_insurance_card_icon,
iconColor: AppColors.successColor,
iconSize: 15.h,
text: "${LocaleKeys.updateInsurance.tr(context: context)} ${LocaleKeys.updateInsuranceSubtitle.tr(context: context)}",
onPressed: () {
insuranceViewModel.setIsInsuranceUpdateDetailsLoading(true);
insuranceViewModel.getPatientInsuranceDetailsForUpdate(
appState.getAuthenticatedUser()!.patientId.toString(), appState.getAuthenticatedUser()!.patientIdentificationNo.toString());
showCommonBottomSheetWithoutHeight(context,
child: PatientInsuranceCardUpdateCard(), callBackFunc: () {}, title: "", isCloseButtonVisible: false, isFullScreen: false);
},
backgroundColor: AppColors.bgGreenColor.withOpacity(0.20),
borderColor: AppColors.bgGreenColor.withOpacity(0.0),
textColor: AppColors.bgGreenColor,
fontSize: 14,
fontWeight: FontWeight.w500,
borderRadius: 12,
padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
height: 40.h,
).paddingSymmetrical(64.h, 0.h),
),
),
], ],
); );
}), }),

@ -8,6 +8,7 @@ import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
import 'package:hmg_patient_app_new/extensions/widget_extensions.dart'; import 'package:hmg_patient_app_new/extensions/widget_extensions.dart';
import 'package:hmg_patient_app_new/features/insurance/insurance_view_model.dart'; import 'package:hmg_patient_app_new/features/insurance/insurance_view_model.dart';
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart'; import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
import 'package:hmg_patient_app_new/presentation/lab/lab_result_item_view.dart';
import 'package:hmg_patient_app_new/theme/colors.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/buttons/custom_button.dart';
import 'package:hmg_patient_app_new/widgets/chip/app_custom_chip_widget.dart'; import 'package:hmg_patient_app_new/widgets/chip/app_custom_chip_widget.dart';
@ -25,6 +26,7 @@ class InsuranceHistory extends StatelessWidget {
return Consumer<InsuranceViewModel>(builder: (context, insuranceVM, child) { return Consumer<InsuranceViewModel>(builder: (context, insuranceVM, child) {
return Column( return Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [ children: [
Row( Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
@ -36,72 +38,85 @@ class InsuranceHistory extends StatelessWidget {
], ],
).paddingSymmetrical(24.h, 24.h), ).paddingSymmetrical(24.h, 24.h),
insuranceVM.isInsuranceHistoryLoading insuranceVM.isInsuranceHistoryLoading
? const MoviesShimmerWidget().paddingSymmetrical(24.h, 24.h) ? LabResultItemView(
: ListView.separated( onTap: () {},
itemCount: insuranceVM.patientInsuranceCardHistoryList.length, labOrder: null,
shrinkWrap: true, index: 0,
padding: const EdgeInsets.only(left: 0, right: 8), isLoading: true,
itemBuilder: (context, index) { ).paddingSymmetrical(24.h, 24.h)
return AnimationConfiguration.staggeredList( : insuranceVM.patientInsuranceCardHistoryList.isNotEmpty
position: index, ? ListView.separated(
duration: const Duration(milliseconds: 1000), itemCount: insuranceVM.patientInsuranceCardHistoryList.length,
child: SlideAnimation( shrinkWrap: true,
verticalOffset: 100.0, padding: const EdgeInsets.only(left: 0, right: 8),
child: FadeInAnimation( itemBuilder: (context, index) {
child: Container( return AnimationConfiguration.staggeredList(
// height: 120.h, position: index,
decoration: RoundedRectangleBorder().toSmoothCornerDecoration( duration: const Duration(milliseconds: 1000),
color: AppColors.whiteColor, child: SlideAnimation(
borderRadius: 24, verticalOffset: 100.0,
), child: FadeInAnimation(
child: Column( child: Container(
crossAxisAlignment: CrossAxisAlignment.start, // height: 120.h,
children: [ decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
Row( color: AppColors.whiteColor,
children: [ borderRadius: 24,
CustomButton(
text: insuranceVM.patientInsuranceCardHistoryList[index].statusDescription!,
onPressed: () {},
backgroundColor: AppColors.primaryRedColor.withOpacity(0.1),
borderColor: AppColors.primaryRedColor.withOpacity(0.0),
textColor: AppColors.primaryRedColor,
fontSize: 10,
fontWeight: FontWeight.w500,
borderRadius: 8,
padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
height: 30.h,
),
],
), ),
SizedBox(height: 8.h), child: Column(
// "Haroon Amjad".toText16(weight: FontWeight.w600), crossAxisAlignment: CrossAxisAlignment.start,
SizedBox(height: 8.h),
Row(
children: [ children: [
Wrap( Row(
direction: Axis.horizontal,
spacing: 4.h,
runSpacing: 4.h,
children: [ children: [
AppCustomChipWidget( CustomButton(
labelText: "File No.: ${insuranceVM.patientInsuranceCardHistoryList[index].patientID}", text: insuranceVM.patientInsuranceCardHistoryList[index].statusDescription!,
onPressed: () {},
backgroundColor: AppColors.primaryRedColor.withOpacity(0.1),
borderColor: AppColors.primaryRedColor.withOpacity(0.0),
textColor: AppColors.primaryRedColor,
fontSize: 10,
fontWeight: FontWeight.w500,
borderRadius: 8,
padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
height: 30.h,
), ),
AppCustomChipWidget( ],
labelText: insuranceVM.patientInsuranceCardHistoryList[index].createdOn!, ),
SizedBox(height: 8.h),
// "Haroon Amjad".toText16(weight: FontWeight.w600),
SizedBox(height: 8.h),
Row(
children: [
Wrap(
direction: Axis.horizontal,
spacing: 4.h,
runSpacing: 4.h,
children: [
AppCustomChipWidget(
labelText: "File No.: ${insuranceVM.patientInsuranceCardHistoryList[index].patientID}",
),
AppCustomChipWidget(
labelText: insuranceVM.patientInsuranceCardHistoryList[index].createdOn!,
),
],
), ),
], ],
), ),
], ],
), ).paddingSymmetrical(16.h, 16.h),
], ).paddingSymmetrical(24.h, 0.h),
).paddingSymmetrical(16.h, 16.h), ),
).paddingSymmetrical(24.h, 0.h), ),
), );
), },
); separatorBuilder: (BuildContext cxt, int index) => SizedBox(height: 16.h),
}, )
separatorBuilder: (BuildContext cxt, int index) => SizedBox(height: 16.h), : Utils.getNoDataWidget(
), context,
noDataText: "No insurance update requests found.".needTranslation,
// isSmallWidget: true,
// width: 62,
// height: 62,
),
], ],
); );
}); });

@ -8,6 +8,7 @@ import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
import 'package:hmg_patient_app_new/extensions/widget_extensions.dart'; import 'package:hmg_patient_app_new/extensions/widget_extensions.dart';
import 'package:hmg_patient_app_new/features/insurance/insurance_view_model.dart'; import 'package:hmg_patient_app_new/features/insurance/insurance_view_model.dart';
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart'; import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
import 'package:hmg_patient_app_new/presentation/lab/lab_result_item_view.dart';
import 'package:hmg_patient_app_new/theme/colors.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/buttons/custom_button.dart';
import 'package:hmg_patient_app_new/widgets/chip/app_custom_chip_widget.dart'; import 'package:hmg_patient_app_new/widgets/chip/app_custom_chip_widget.dart';
@ -23,6 +24,7 @@ class PatientInsuranceCardUpdateCard extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
insuranceViewModel = Provider.of<InsuranceViewModel>(context); insuranceViewModel = Provider.of<InsuranceViewModel>(context);
return Column( return Column(
mainAxisSize: MainAxisSize.min,
children: [ children: [
Row( Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
@ -34,57 +36,63 @@ class PatientInsuranceCardUpdateCard extends StatelessWidget {
], ],
).paddingSymmetrical(24.h, 24.h), ).paddingSymmetrical(24.h, 24.h),
insuranceViewModel.isInsuranceUpdateDetailsLoading insuranceViewModel.isInsuranceUpdateDetailsLoading
? const MoviesShimmerWidget().paddingSymmetrical(24.h, 24.h) ? LabResultItemView(
: Container( onTap: () {},
// height: 120.h, labOrder: null,
decoration: RoundedRectangleBorder().toSmoothCornerDecoration( index: 0,
color: AppColors.whiteColor, isLoading: true,
borderRadius: 24, ).paddingSymmetrical(24.h, 24.h)
), : insuranceViewModel.patientInsuranceUpdateResponseModel != null
child: Column( ? Container(
crossAxisAlignment: CrossAxisAlignment.start, decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
children: [ color: AppColors.whiteColor,
"Haroon Amjad".toText16(weight: FontWeight.w600), borderRadius: 24,
"Policy: ${insuranceViewModel.patientInsuranceUpdateResponseModel!.policyNumber}".toText12(isBold: true, color: AppColors.lightGrayColor),
SizedBox(height: 8.h),
Row(
children: [
insuranceViewModel.patientInsuranceUpdateResponseModel!.companyName!.toText12(isBold: true),
SizedBox(
width: 6.h,
),
Container(
padding: EdgeInsets.symmetric(horizontal: 6.h, vertical: 3.h),
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.infoColor,
borderRadius: 50,
),
child: insuranceViewModel.patientInsuranceUpdateResponseModel!.subCategory!.toText8(isBold: true, color: AppColors.whiteColor),
),
],
), ),
SizedBox(height: 8.h), child: Column(
Row( crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Wrap( "Haroon Amjad".toText16(weight: FontWeight.w600),
direction: Axis.horizontal, "Policy: ${insuranceViewModel.patientInsuranceUpdateResponseModel!.policyNumber}".toText12(isBold: true, color: AppColors.lightGrayColor),
spacing: 4.h, SizedBox(height: 8.h),
runSpacing: 4.h, Row(
children: [ children: [
AppCustomChipWidget( insuranceViewModel.patientInsuranceUpdateResponseModel!.companyName!.toText12(isBold: true),
icon: AppAssets.doctor_calendar_icon, SizedBox(
labelText: "${LocaleKeys.expiryOn.tr(context: context)} ${insuranceViewModel.patientInsuranceUpdateResponseModel!.effectiveTo}", width: 6.h,
),
Container(
padding: EdgeInsets.symmetric(horizontal: 6.h, vertical: 3.h),
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.infoColor,
borderRadius: 50,
),
child: insuranceViewModel.patientInsuranceUpdateResponseModel!.subCategory!.toText8(isBold: true, color: AppColors.whiteColor),
), ),
AppCustomChipWidget( ],
labelText: "Member ID: ${insuranceViewModel.patientInsuranceUpdateResponseModel!.memberID!}", ),
SizedBox(height: 8.h),
Row(
children: [
Wrap(
direction: Axis.horizontal,
spacing: 4.h,
runSpacing: 4.h,
children: [
AppCustomChipWidget(
icon: AppAssets.doctor_calendar_icon,
labelText: "${LocaleKeys.expiryOn.tr(context: context)} ${insuranceViewModel.patientInsuranceUpdateResponseModel!.effectiveTo}",
),
AppCustomChipWidget(
labelText: "Member ID: ${insuranceViewModel.patientInsuranceUpdateResponseModel!.memberID!}",
),
],
), ),
], ],
), ),
], ],
), ).paddingSymmetrical(16.h, 16.h),
], ).paddingSymmetrical(24.h, 0.h)
).paddingSymmetrical(16.h, 16.h), : Utils.getNoDataWidget(context, noDataText: "No insurance data found...".needTranslation),
).paddingSymmetrical(24.h, 0.h),
SizedBox( SizedBox(
height: 24.h, height: 24.h,
), ),
@ -92,9 +100,9 @@ class PatientInsuranceCardUpdateCard extends StatelessWidget {
icon: AppAssets.insurance_active_icon, icon: AppAssets.insurance_active_icon,
iconColor: AppColors.whiteColor, iconColor: AppColors.whiteColor,
iconSize: 20.h, iconSize: 20.h,
text: "Update Insurance", text: "${LocaleKeys.updateInsurance.tr(context: context)} ${LocaleKeys.updateInsuranceSubtitle.tr(context: context)}",
onPressed: () {}, onPressed: () {},
backgroundColor: AppColors.successColor, backgroundColor: insuranceViewModel.patientInsuranceUpdateResponseModel != null ? AppColors.successColor : AppColors.lightGrayBGColor,
borderColor: AppColors.successColor.withOpacity(0.01), borderColor: AppColors.successColor.withOpacity(0.01),
textColor: AppColors.whiteColor, textColor: AppColors.whiteColor,
fontSize: 16, fontSize: 16,
@ -103,9 +111,6 @@ class PatientInsuranceCardUpdateCard extends StatelessWidget {
padding: EdgeInsets.fromLTRB(10, 0, 10, 0), padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
height: 56.h, height: 56.h,
).paddingSymmetrical(24.h, 0.h), ).paddingSymmetrical(24.h, 0.h),
SizedBox(
height: 24.h,
),
], ],
); );
} }

@ -94,11 +94,11 @@ class PatientInsuranceCard extends StatelessWidget {
insuranceViewModel.setIsInsuranceUpdateDetailsLoading(true); insuranceViewModel.setIsInsuranceUpdateDetailsLoading(true);
insuranceViewModel.getPatientInsuranceDetailsForUpdate( insuranceViewModel.getPatientInsuranceDetailsForUpdate(
appState.getAuthenticatedUser()!.patientId.toString(), appState.getAuthenticatedUser()!.patientIdentificationNo.toString()); appState.getAuthenticatedUser()!.patientId.toString(), appState.getAuthenticatedUser()!.patientIdentificationNo.toString());
showCommonBottomSheet(context, showCommonBottomSheetWithoutHeight(context,
child: PatientInsuranceCardUpdateCard(), child: PatientInsuranceCardUpdateCard(),
callBackFunc: (str) {}, callBackFunc: () {},
title: "", title: "",
height: ResponsiveExtension.screenHeight * 0.42, // height: ResponsiveExtension.screenHeight * 0.42,
isCloseButtonVisible: false, isCloseButtonVisible: false,
isFullScreen: false); isFullScreen: false);
}, },

@ -28,9 +28,11 @@ import 'package:hmg_patient_app_new/presentation/appointments/my_doctors_page.da
import 'package:hmg_patient_app_new/presentation/book_appointment/book_appointment_page.dart'; import 'package:hmg_patient_app_new/presentation/book_appointment/book_appointment_page.dart';
import 'package:hmg_patient_app_new/presentation/book_appointment/widgets/appointment_calendar.dart'; import 'package:hmg_patient_app_new/presentation/book_appointment/widgets/appointment_calendar.dart';
import 'package:hmg_patient_app_new/presentation/insurance/insurance_home_page.dart'; import 'package:hmg_patient_app_new/presentation/insurance/insurance_home_page.dart';
import 'package:hmg_patient_app_new/presentation/insurance/widgets/insurance_update_details_card.dart';
import 'package:hmg_patient_app_new/presentation/insurance/widgets/patient_insurance_card.dart'; import 'package:hmg_patient_app_new/presentation/insurance/widgets/patient_insurance_card.dart';
import 'package:hmg_patient_app_new/presentation/lab/lab_result_item_view.dart';
import 'package:hmg_patient_app_new/widgets/appbar/collapsing_list_view.dart'; import 'package:hmg_patient_app_new/widgets/appbar/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_report/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/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/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/lab_rad_card.dart';
@ -566,28 +568,28 @@ class _MedicalFilePageState extends State<MedicalFilePage> {
horizontalOffset: 100.0, horizontalOffset: 100.0,
child: FadeInAnimation( child: FadeInAnimation(
child: SizedBox( child: SizedBox(
width: 80.h, width: 80.h,
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center,
children: [ children: [
Image.network( Image.network(
myAppointmentsVM.patientMyDoctorsList[index].doctorImageURL!, myAppointmentsVM.patientMyDoctorsList[index].doctorImageURL!,
width: 64.h, width: 64.h,
height: 64.h, height: 64.h,
fit: BoxFit.fill, fit: BoxFit.fill,
).circle(100).toShimmer2(isShow: false, radius: 50.h), ).circle(100).toShimmer2(isShow: false, radius: 50.h),
SizedBox(height: 8.h), SizedBox(height: 8.h),
Expanded( Expanded(
child: (myAppointmentsVM.patientMyDoctorsList[index].doctorName) child: (myAppointmentsVM.patientMyDoctorsList[index].doctorName)
.toString() .toString()
.toText12(fontWeight: FontWeight.w500, isCenter: true, maxLine: 2) .toText12(fontWeight: FontWeight.w500, isCenter: true, maxLine: 2)
.toShimmer2(isShow: false), .toShimmer2(isShow: false),
),
],
), ),
], ),
), ),
), ),
),
),
) )
: Utils.getNoDataWidget(context, noDataText: "You don't have any completed visits yet.".needTranslation, isSmallWidget: true, width: 62, height: 62) : Utils.getNoDataWidget(context, noDataText: "You don't have any completed visits yet.".needTranslation, isSmallWidget: true, width: 62, height: 62)
.paddingSymmetrical(24.h, 0.h); .paddingSymmetrical(24.h, 0.h);
@ -646,7 +648,12 @@ class _MedicalFilePageState extends State<MedicalFilePage> {
children: [ children: [
Consumer<InsuranceViewModel>(builder: (context, insuranceVM, child) { Consumer<InsuranceViewModel>(builder: (context, insuranceVM, child) {
return insuranceVM.isInsuranceLoading return insuranceVM.isInsuranceLoading
? const MoviesShimmerWidget().paddingSymmetrical(24.h, 0.0) ? LabResultItemView(
onTap: () {},
labOrder: null,
index: index,
isLoading: true,
).paddingSymmetrical(24.h, 0.0)
: insuranceVM.patientInsuranceList.isNotEmpty : insuranceVM.patientInsuranceList.isNotEmpty
? PatientInsuranceCard( ? PatientInsuranceCard(
insuranceCardDetailsModel: insuranceVM.patientInsuranceList.first, insuranceCardDetailsModel: insuranceVM.patientInsuranceList.first,
@ -654,7 +661,33 @@ class _MedicalFilePageState extends State<MedicalFilePage> {
DateUtil.convertStringToDate(insuranceVM.patientInsuranceList.first.cardValidTo), DateUtil.convertStringToDate(insuranceVM.patientInsuranceList.first.cardValidTo),
), ),
) )
: SizedBox.shrink(); : Utils.getNoDataWidget(
context,
noDataText: "You don't have insurance registered with HMG.".needTranslation,
isSmallWidget: true,
width: 62,
height: 62,
callToActionButton: CustomButton(
icon: AppAssets.update_insurance_card_icon,
iconColor: AppColors.successColor,
iconSize: 15.h,
text: "${LocaleKeys.updateInsurance.tr(context: context)} ${LocaleKeys.updateInsuranceSubtitle.tr(context: context)}",
onPressed: () {
insuranceViewModel.setIsInsuranceUpdateDetailsLoading(true);
insuranceViewModel.getPatientInsuranceDetailsForUpdate(
appState.getAuthenticatedUser()!.patientId.toString(), appState.getAuthenticatedUser()!.patientIdentificationNo.toString());
showCommonBottomSheetWithoutHeight(context, child: PatientInsuranceCardUpdateCard(), callBackFunc: () {}, title: "", isCloseButtonVisible: false, isFullScreen: false);
},
backgroundColor: AppColors.bgGreenColor.withOpacity(0.20),
borderColor: AppColors.bgGreenColor.withOpacity(0.0),
textColor: AppColors.bgGreenColor,
fontSize: 14,
fontWeight: FontWeight.w500,
borderRadius: 12,
padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
height: 40.h,
).paddingSymmetrical(64.h, 0.h),
);
}), }),
SizedBox(height: 10.h), SizedBox(height: 10.h),
GridView( GridView(
@ -718,11 +751,17 @@ class _MedicalFilePageState extends State<MedicalFilePage> {
patientSickLeavesResponseModel: medicalFileVM.patientSickLeaveList.first, patientSickLeavesResponseModel: medicalFileVM.patientSickLeaveList.first,
isLoading: false, isLoading: false,
).paddingSymmetrical(24.h, 0.0) ).paddingSymmetrical(24.h, 0.0)
: SizedBox.shrink(); : Utils.getNoDataWidget(
context,
noDataText: "You don't have any sick leaves yet.".needTranslation,
isSmallWidget: true,
width: 62,
height: 62,
);
}), }),
SizedBox(height: 16.h), SizedBox(height: 16.h),
GridView( GridView(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 3, crossAxisSpacing: 13, mainAxisSpacing: 13), gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 3, crossAxisSpacing: 6.5, mainAxisSpacing: 6.5),
physics: NeverScrollableScrollPhysics(), physics: NeverScrollableScrollPhysics(),
padding: EdgeInsets.zero, padding: EdgeInsets.zero,
shrinkWrap: true, shrinkWrap: true,

@ -1,94 +0,0 @@
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/widgets/appbar/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<MedicalReportsPage> createState() => _MedicalReportsPageState();
}
class _MedicalReportsPageState extends State<MedicalReportsPage> {
late MedicalFileViewModel medicalFileViewModel;
@override
Widget build(BuildContext context) {
medicalFileViewModel = Provider.of<MedicalFileViewModel>(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<MedicalFileViewModel>(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),
],
),
),
),
);
}
}

@ -0,0 +1,61 @@
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/my_appointments/my_appointments_view_model.dart';
import 'package:hmg_patient_app_new/presentation/appointments/widgets/appointment_card.dart';
import 'package:hmg_patient_app_new/theme/colors.dart';
import 'package:hmg_patient_app_new/widgets/appbar/collapsing_list_view.dart';
import 'package:provider/provider.dart';
class MedicalReportRequestPage extends StatelessWidget {
MedicalReportRequestPage({super.key});
late MedicalFileViewModel medicalFileViewModel;
@override
Widget build(BuildContext context) {
medicalFileViewModel = Provider.of<MedicalFileViewModel>(context, listen: false);
return CollapsingListView(
title: "Medical Reports".needTranslation,
isClose: true,
child: Column(
children: [
ListView.separated(
padding: EdgeInsets.only(top: 24.h),
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
itemCount: medicalFileViewModel.patientMedicalReportAppointmentHistoryList.length,
itemBuilder: (context, index) {
return 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: AppointmentCard(
patientAppointmentHistoryResponseModel: medicalFileViewModel.patientMedicalReportAppointmentHistoryList[index],
myAppointmentsViewModel: Provider.of<MyAppointmentsViewModel>(context, listen: false),
medicalFileViewModel: medicalFileViewModel,
isLoading: false,
isFromHomePage: false,
isFromMedicalReport: true,
),
).paddingSymmetrical(24.h, 0.h),
),
),
);
},
separatorBuilder: (BuildContext cxt, int index) => SizedBox(height: 16.h),
),
],
),
);
}
}

@ -0,0 +1,176 @@
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/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/presentation/medical_report/medical_report_request_page.dart';
import 'package:hmg_patient_app_new/widgets/appbar/collapsing_list_view.dart';
import 'package:hmg_patient_app_new/presentation/medical_report/widgets/patient_medical_report_card.dart';
import 'package:hmg_patient_app_new/theme/colors.dart';
import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart';
import 'package:hmg_patient_app_new/widgets/common_bottom_sheet.dart';
import 'package:hmg_patient_app_new/widgets/custom_tab_bar.dart';
import 'package:hmg_patient_app_new/widgets/loader/bottomsheet_loader.dart';
import 'package:hmg_patient_app_new/widgets/routes/custom_page_route.dart';
import 'package:provider/provider.dart';
class MedicalReportsPage extends StatefulWidget {
const MedicalReportsPage({super.key});
@override
State<MedicalReportsPage> createState() => _MedicalReportsPageState();
}
class _MedicalReportsPageState extends State<MedicalReportsPage> {
late MedicalFileViewModel medicalFileViewModel;
@override
Widget build(BuildContext context) {
medicalFileViewModel = Provider.of<MedicalFileViewModel>(context, listen: false);
return Scaffold(
backgroundColor: AppColors.bgScaffoldColor,
body: Column(
children: [
Expanded(
child: 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<MedicalFileViewModel>(builder: (context, medicalFileVM, child) {
return ListView.separated(
padding: EdgeInsets.only(top: 24.h),
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
itemCount: medicalFileViewModel.isPatientMedicalReportsListLoading
? 3
: 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)
: medicalFileViewModel.patientMedicalReportList.isNotEmpty
? AnimationConfiguration.staggeredList(
position: index,
duration: const Duration(milliseconds: 500),
child: SlideAnimation(
verticalOffset: 100.0,
child: FadeInAnimation(
child: AnimatedContainer(
duration: Duration(milliseconds: 300),
curve: Curves.easeInOut,
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),
),
),
)
: Utils.getNoDataWidget(context, noDataText: "You don't have any medical reports yet.".needTranslation).paddingSymmetrical(24.h, 0.h);
},
separatorBuilder: (BuildContext cxt, int index) => SizedBox(height: 16.h),
);
}),
SizedBox(height: 24.h),
],
),
),
),
),
Container(
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.whiteColor,
borderRadius: 24.h,
hasShadow: true,
),
child: CustomButton(
text: "Request medical report".needTranslation,
onPressed: () async {
LoaderBottomSheet.showLoader();
await medicalFileViewModel.getPatientMedicalReportAppointmentsList(onSuccess: (val) async {
LoaderBottomSheet.hideLoader();
bool? value = await Navigator.of(context).push(
CustomPageRoute(
page: MedicalReportRequestPage(),
fullScreenDialog: true,
direction: AxisDirection.down,
),
);
if (value != null) {
showConfirmRequestMedicalReportBottomSheet();
}
}, onError: (err) {
LoaderBottomSheet.hideLoader();
showCommonBottomSheetWithoutHeight(
context,
child: Utils.getErrorWidget(loadingText: "You do not have any appointments to request a medical report.".needTranslation),
callBackFunc: () {},
isFullScreen: false,
isCloseButtonVisible: true,
);
});
},
backgroundColor: AppColors.primaryRedColor,
borderColor: AppColors.primaryRedColor,
textColor: AppColors.whiteColor,
fontSize: 16,
fontWeight: FontWeight.w500,
borderRadius: 12,
padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
height: 45.h,
icon: AppAssets.requests,
iconColor: AppColors.whiteColor,
iconSize: 20.h,
).paddingSymmetrical(24.h, 24.h),
),
],
),
);
}
showConfirmRequestMedicalReportBottomSheet() {
showCommonBottomSheetWithoutHeight(
title: LocaleKeys.notice.tr(context: context),
context,
child: Utils.getWarningWidget(
loadingText: "Are you sure you want to request a medical report for this appointment?".needTranslation,
isShowActionButtons: true,
onCancelTap: () {
Navigator.pop(context);
},
onConfirmTap: () async {
Navigator.pop(context);
}),
callBackFunc: () {},
isFullScreen: false,
isCloseButtonVisible: true,
);
}
}

@ -55,7 +55,7 @@ dependencies:
uuid: ^4.5.1 uuid: ^4.5.1
health: ^13.1.3 health: ^13.1.3
# health: 12.0.1 # health: 12.0.1
fl_chart: ^1.0.0 fl_chart: 1.0.0
geolocator: ^14.0.2 geolocator: ^14.0.2
dropdown_search: ^6.0.2 dropdown_search: ^6.0.2
google_maps_flutter: ^2.12.3 google_maps_flutter: ^2.12.3

Loading…
Cancel
Save