Added 'send report to email' feature

faiz_dev
faizatflutter 4 days ago
parent 3f5bd0a759
commit 001808488c

@ -39,6 +39,11 @@ abstract class HealthTrackersRepo {
required int lineItemNo, required int lineItemNo,
}); });
/// Send blood sugar report by email.
Future<Either<Failure, GenericApiModel<dynamic>>> sendBloodSugarReportByEmail({
required String email,
});
// ==================== BLOOD PRESSURE ==================== // ==================== BLOOD PRESSURE ====================
/// Get blood pressure result averages (week, month, year). /// Get blood pressure result averages (week, month, year).
Future<Either<Failure, GenericApiModel<dynamic>>> getBloodPressureResultAverage(); Future<Either<Failure, GenericApiModel<dynamic>>> getBloodPressureResultAverage();
@ -68,6 +73,11 @@ abstract class HealthTrackersRepo {
required int lineItemNo, required int lineItemNo,
}); });
/// Send blood pressure report by email.
Future<Either<Failure, GenericApiModel<dynamic>>> sendBloodPressureReportByEmail({
required String email,
});
// ==================== WEIGHT MEASUREMENT ==================== // ==================== WEIGHT MEASUREMENT ====================
/// Get weight measurement result averages (week, month, year). /// Get weight measurement result averages (week, month, year).
Future<Either<Failure, GenericApiModel<dynamic>>> getWeightMeasurementResultAverage(); Future<Either<Failure, GenericApiModel<dynamic>>> getWeightMeasurementResultAverage();
@ -94,6 +104,11 @@ abstract class HealthTrackersRepo {
Future<Either<Failure, GenericApiModel<dynamic>>> deactivateWeightMeasurementStatus({ Future<Either<Failure, GenericApiModel<dynamic>>> deactivateWeightMeasurementStatus({
required int lineItemNo, required int lineItemNo,
}); });
/// Send weight report by email.
Future<Either<Failure, GenericApiModel<dynamic>>> sendWeightReportByEmail({
required String email,
});
} }
class HealthTrackersRepoImp implements HealthTrackersRepo { class HealthTrackersRepoImp implements HealthTrackersRepo {
@ -322,6 +337,42 @@ class HealthTrackersRepoImp implements HealthTrackersRepo {
} }
} }
@override
Future<Either<Failure, GenericApiModel<dynamic>>> sendBloodSugarReportByEmail({
required String email,
}) async {
try {
GenericApiModel<dynamic>? apiResponse;
Failure? failure;
Map<String, dynamic> body = {
'To': email,
};
await apiClient.post(
ApiConsts.sendAverageBloodSugarReport,
body: body,
onFailure: (error, statusCode, {messageStatus, failureType}) {
failure = failureType;
},
onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
apiResponse = GenericApiModel<dynamic>(
messageStatus: messageStatus,
statusCode: statusCode,
errorMessage: errorMessage,
data: response,
);
},
);
if (failure != null) return Left(failure!);
if (apiResponse == null) return Left(ServerFailure("Unknown error"));
return Right(apiResponse!);
} catch (e) {
return Left(UnknownFailure(e.toString()));
}
}
// ==================== BLOOD PRESSURE METHODS ==================== // ==================== BLOOD PRESSURE METHODS ====================
@override @override
@ -538,6 +589,42 @@ class HealthTrackersRepoImp implements HealthTrackersRepo {
} }
} }
@override
Future<Either<Failure, GenericApiModel<dynamic>>> sendBloodPressureReportByEmail({
required String email,
}) async {
try {
GenericApiModel<dynamic>? apiResponse;
Failure? failure;
Map<String, dynamic> body = {
'To': email,
};
await apiClient.post(
ApiConsts.sendAverageBloodPressureReport,
body: body,
onFailure: (error, statusCode, {messageStatus, failureType}) {
failure = failureType;
},
onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
apiResponse = GenericApiModel<dynamic>(
messageStatus: messageStatus,
statusCode: statusCode,
errorMessage: errorMessage,
data: response,
);
},
);
if (failure != null) return Left(failure!);
if (apiResponse == null) return Left(ServerFailure("Unknown error"));
return Right(apiResponse!);
} catch (e) {
return Left(UnknownFailure(e.toString()));
}
}
// ==================== WEIGHT MEASUREMENT METHODS ==================== // ==================== WEIGHT MEASUREMENT METHODS ====================
@override @override
@ -715,9 +802,7 @@ class HealthTrackersRepoImp implements HealthTrackersRepo {
} }
@override @override
Future<Either<Failure, GenericApiModel<dynamic>>> deactivateWeightMeasurementStatus({ Future<Either<Failure, GenericApiModel<dynamic>>> deactivateWeightMeasurementStatus({required int lineItemNo}) async {
required int lineItemNo,
}) async {
try { try {
GenericApiModel<dynamic>? apiResponse; GenericApiModel<dynamic>? apiResponse;
Failure? failure; Failure? failure;
@ -749,4 +834,40 @@ class HealthTrackersRepoImp implements HealthTrackersRepo {
return Left(UnknownFailure(e.toString())); return Left(UnknownFailure(e.toString()));
} }
} }
@override
Future<Either<Failure, GenericApiModel<dynamic>>> sendWeightReportByEmail({
required String email,
}) async {
try {
GenericApiModel<dynamic>? apiResponse;
Failure? failure;
Map<String, dynamic> body = {
'To': email,
};
await apiClient.post(
ApiConsts.sendAverageBodyWeightReport,
body: body,
onFailure: (error, statusCode, {messageStatus, failureType}) {
failure = failureType;
},
onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
apiResponse = GenericApiModel<dynamic>(
messageStatus: messageStatus,
statusCode: statusCode,
errorMessage: errorMessage,
data: response,
);
},
);
if (failure != null) return Left(failure!);
if (apiResponse == null) return Left(ServerFailure("Unknown error"));
return Right(apiResponse!);
} catch (e) {
return Left(UnknownFailure(e.toString()));
}
}
} }

@ -219,3 +219,4 @@ class MyApp extends StatelessWidget {
} }
} }
// flutter pub run easy_localization:generate -S assets/langs -f keys -o locale_keys.g.dart // flutter pub run easy_localization:generate -S assets/langs -f keys -o locale_keys.g.dart

@ -2,6 +2,7 @@ import 'package:fl_chart/fl_chart.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_export.dart'; import 'package:hmg_patient_app_new/core/app_export.dart';
import 'package:hmg_patient_app_new/core/app_state.dart';
import 'package:hmg_patient_app_new/core/common_models/data_points.dart'; import 'package:hmg_patient_app_new/core/common_models/data_points.dart';
import 'package:hmg_patient_app_new/core/dependencies.dart'; import 'package:hmg_patient_app_new/core/dependencies.dart';
import 'package:hmg_patient_app_new/core/enums.dart'; import 'package:hmg_patient_app_new/core/enums.dart';
@ -9,8 +10,6 @@ import 'package:hmg_patient_app_new/core/utils/utils.dart';
import 'package:hmg_patient_app_new/extensions/route_extensions.dart'; import 'package:hmg_patient_app_new/extensions/route_extensions.dart';
import 'package:hmg_patient_app_new/extensions/string_extensions.dart'; import 'package:hmg_patient_app_new/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/health_trackers/models/blood_pressure/week_blood_pressure_result_average.dart';
import 'package:hmg_patient_app_new/features/health_trackers/models/blood_pressure/year_blood_pressure_result_average.dart';
import 'package:hmg_patient_app_new/features/health_trackers/models/blood_sugar/week_diabetic_result_average.dart'; import 'package:hmg_patient_app_new/features/health_trackers/models/blood_sugar/week_diabetic_result_average.dart';
import 'package:hmg_patient_app_new/features/health_trackers/models/blood_sugar/year_diabetic_result_average.dart'; import 'package:hmg_patient_app_new/features/health_trackers/models/blood_sugar/year_diabetic_result_average.dart';
import 'package:hmg_patient_app_new/features/health_trackers/models/weight/week_weight_measurement_result_average.dart'; import 'package:hmg_patient_app_new/features/health_trackers/models/weight/week_weight_measurement_result_average.dart';
@ -22,7 +21,10 @@ import 'package:hmg_patient_app_new/theme/colors.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/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';
import 'package:hmg_patient_app_new/widgets/common_bottom_sheet.dart';
import 'package:hmg_patient_app_new/widgets/graph/custom_graph.dart'; import 'package:hmg_patient_app_new/widgets/graph/custom_graph.dart';
import 'package:hmg_patient_app_new/widgets/input_widget.dart';
import 'package:hmg_patient_app_new/widgets/loader/bottomsheet_loader.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:shimmer/shimmer.dart'; import 'package:shimmer/shimmer.dart';
@ -1028,7 +1030,182 @@ class _HealthTrackerDetailPageState extends State<HealthTrackerDetailPage> {
} }
void onSendEmailPressed(BuildContext context) async { void onSendEmailPressed(BuildContext context) async {
// TODO: Implement send email functionality _showEmailInputBottomSheet(context);
}
/// Show email input bottom sheet
void _showEmailInputBottomSheet(BuildContext context) {
final viewModel = context.read<HealthTrackersViewModel>();
final appState = getIt.get<AppState>();
final dialogService = getIt.get<DialogService>();
// Get user's email from authenticated user
final userEmail = appState.getAuthenticatedUser()?.emailAddress ?? '';
// Create email controller and pre-fill if available
final emailController = TextEditingController(text: userEmail);
dialogService.showFamilyBottomSheetWithoutHWithChild(
label: "Send Report by Email".needTranslation,
message: "",
child: _buildEmailInputContent(
context: context,
emailController: emailController,
viewModel: viewModel,
dialogService: dialogService,
),
onOkPressed: () {},
);
}
/// Build email input content
Widget _buildEmailInputContent({
required BuildContext context,
required TextEditingController emailController,
required HealthTrackersViewModel viewModel,
required DialogService dialogService,
}) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
"Enter your email address to receive the report".needTranslation.toText14(
color: AppColors.textColor,
weight: FontWeight.w400,
),
SizedBox(height: 16.h),
// Email Input Field using TextInputWidget
TextInputWidget(
padding: EdgeInsets.symmetric(horizontal: 8.w),
labelText: "Email Address".needTranslation,
hintText: "Enter email address".needTranslation,
controller: emailController,
keyboardType: TextInputType.emailAddress,
isEnable: true,
isBorderAllowed: true,
isAllowRadius: true,
),
SizedBox(height: 24.h),
// Send Button
Row(
children: [
Expanded(
child: CustomButton(
height: 56.h,
text: "Send Report".needTranslation,
onPressed: () {
_sendEmailReport(
context: context,
email: emailController.text.trim(),
viewModel: viewModel,
dialogService: dialogService,
);
},
textColor: AppColors.whiteColor,
),
),
],
),
],
);
}
/// Send email report based on tracker type
Future<void> _sendEmailReport({
required BuildContext context,
required String email,
required HealthTrackersViewModel viewModel,
required DialogService dialogService,
}) async {
// Validate email
if (email.isEmpty) {
dialogService.showErrorBottomSheet(
message: "Please enter your email address".needTranslation,
);
return;
}
// Basic email validation
final emailRegex = RegExp(r'^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$');
if (!emailRegex.hasMatch(email)) {
dialogService.showErrorBottomSheet(
message: "Please enter a valid email address".needTranslation,
);
return;
}
// Close the email input bottom sheet
Navigator.of(context).pop();
// Call appropriate email function based on tracker type
switch (widget.trackerType) {
case HealthTrackerTypeEnum.bloodSugar:
LoaderBottomSheet.showLoader(loadingText: "Please wait".needTranslation);
await viewModel.sendBloodSugarReportByEmail(
email: email,
onSuccess: () {
LoaderBottomSheet.hideLoader();
_showSuccessMessage(context, dialogService);
},
onFailure: (error) {
LoaderBottomSheet.hideLoader();
dialogService.showErrorBottomSheet(message: error);
},
);
break;
case HealthTrackerTypeEnum.bloodPressure:
LoaderBottomSheet.showLoader(loadingText: "Please wait".needTranslation);
await viewModel.sendBloodPressureReportByEmail(
email: email,
onSuccess: () {
LoaderBottomSheet.hideLoader();
_showSuccessMessage(context, dialogService);
},
onFailure: (error) {
LoaderBottomSheet.hideLoader();
dialogService.showErrorBottomSheet(message: error);
},
);
break;
case HealthTrackerTypeEnum.weightTracker:
LoaderBottomSheet.showLoader(loadingText: "Please wait".needTranslation);
await viewModel.sendWeightReportByEmail(
email: email,
onSuccess: () {
LoaderBottomSheet.hideLoader();
_showSuccessMessage(context, dialogService);
},
onFailure: (error) {
LoaderBottomSheet.hideLoader();
dialogService.showErrorBottomSheet(message: error);
},
);
break;
}
}
/// Show success message
void _showSuccessMessage(BuildContext context, DialogService dialogService) {
showCommonBottomSheetWithoutHeight(
context,
child: Utils.getSuccessWidget(
loadingText: "Report has been sent to your email successfully".needTranslation,
),
callBackFunc: () {},
isCloseButtonVisible: false,
isDismissible: true,
isFullScreen: false,
);
} }
Widget _buildPageShimmer() { Widget _buildPageShimmer() {

@ -388,6 +388,41 @@ class HealthTrackersViewModel extends ChangeNotifier {
} }
} }
/// Send weight report by email
Future<bool> sendWeightReportByEmail({
required String email,
Function()? onSuccess,
Function(String error)? onFailure,
}) async {
try {
final result = await healthTrackersRepo.sendWeightReportByEmail(
email: email,
);
bool success = false;
result.fold(
(failure) {
errorHandlerService.handleError(failure: failure);
if (onFailure != null) onFailure("Failed to send report by email");
},
(apiModel) {
success = true;
if (onSuccess != null) onSuccess();
},
);
notifyListeners();
return success;
} catch (e) {
log('Error in sendWeightReportByEmail: $e');
if (onFailure != null) onFailure("An error occurred");
return false;
}
}
// ==================== BLOOD PRESSURE TRACKING METHODS ==================== // ==================== BLOOD PRESSURE TRACKING METHODS ====================
/// Fetch blood pressure averages and results /// Fetch blood pressure averages and results
@ -554,6 +589,41 @@ class HealthTrackersViewModel extends ChangeNotifier {
} }
} }
/// Send blood pressure report by email
Future<bool> sendBloodPressureReportByEmail({
required String email,
Function()? onSuccess,
Function(String error)? onFailure,
}) async {
try {
final result = await healthTrackersRepo.sendBloodPressureReportByEmail(
email: email,
);
bool success = false;
result.fold(
(failure) {
errorHandlerService.handleError(failure: failure);
if (onFailure != null) onFailure("Failed to send report by email");
},
(apiModel) {
success = true;
if (onSuccess != null) onSuccess();
},
);
notifyListeners();
return success;
} catch (e) {
log('Error in sendBloodPressureReportByEmail: $e');
if (onFailure != null) onFailure("An error occurred");
return false;
}
}
// ==================== BLOOD SUGAR (DIABETIC) TRACKING METHODS ==================== // ==================== BLOOD SUGAR (DIABETIC) TRACKING METHODS ====================
/// Fetch blood sugar averages and results /// Fetch blood sugar averages and results
@ -746,6 +816,40 @@ class HealthTrackersViewModel extends ChangeNotifier {
} }
} }
/// Send blood sugar report by email
Future<bool> sendBloodSugarReportByEmail({
required String email,
Function()? onSuccess,
Function(String error)? onFailure,
}) async {
try {
final result = await healthTrackersRepo.sendBloodSugarReportByEmail(
email: email,
);
bool success = false;
result.fold(
(failure) {
errorHandlerService.handleError(failure: failure);
if (onFailure != null) onFailure("Failed to send report by email");
},
(apiModel) {
success = true;
if (onSuccess != null) onSuccess();
},
);
notifyListeners();
return success;
} catch (e) {
log('Error in sendBloodSugarReportByEmail: $e');
if (onFailure != null) onFailure("An error occurred");
return false;
}
}
// Validation method // Validation method
String? _validateBloodSugarEntry(String dateTime) { String? _validateBloodSugarEntry(String dateTime) {
// Validate blood sugar value // Validate blood sugar value

@ -7,10 +7,11 @@ import 'package:hmg_patient_app_new/core/app_assets.dart';
import 'package:hmg_patient_app_new/core/app_export.dart'; import 'package:hmg_patient_app_new/core/app_export.dart';
import 'package:hmg_patient_app_new/core/app_state.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/dependencies.dart';
import 'package:hmg_patient_app_new/core/enums.dart';
import 'package:hmg_patient_app_new/core/utils/date_util.dart'; import 'package:hmg_patient_app_new/core/utils/date_util.dart';
import 'package:hmg_patient_app_new/core/utils/size_config.dart'; import 'package:hmg_patient_app_new/core/utils/size_config.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/core/utils/utils.dart';
import 'package:hmg_patient_app_new/extensions/route_extensions.dart';
import 'package:hmg_patient_app_new/extensions/string_extensions.dart'; import 'package:hmg_patient_app_new/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/book_appointments/book_appointments_view_model.dart'; import 'package:hmg_patient_app_new/features/book_appointments/book_appointments_view_model.dart';
@ -234,9 +235,9 @@ class _MedicalFilePageState extends State<MedicalFilePage> {
labelPadding: EdgeInsetsDirectional.only(start: -4.w, end: 6.w), labelPadding: EdgeInsetsDirectional.only(start: -4.w, end: 6.w),
onChipTap: () { onChipTap: () {
navigationService.pushPage( navigationService.pushPage(
page: FamilyMedicalScreen( page: FamilyMedicalScreen(
profiles: medicalFileViewModel.patientFamilyFiles, profiles: medicalFileViewModel.patientFamilyFiles,
onSelect: (FamilyFileResponseModelLists p1) {}, onSelect: (FamilyFileResponseModelLists p1) {},
), ),
); );
}, },
@ -279,7 +280,8 @@ class _MedicalFilePageState extends State<MedicalFilePage> {
iconColor: insuranceVM.isInsuranceExpired ? AppColors.primaryRedColor : AppColors.successColor, iconColor: insuranceVM.isInsuranceExpired ? AppColors.primaryRedColor : AppColors.successColor,
textColor: insuranceVM.isInsuranceExpired ? AppColors.primaryRedColor : AppColors.successColor, textColor: insuranceVM.isInsuranceExpired ? AppColors.primaryRedColor : AppColors.successColor,
iconSize: 12.w, iconSize: 12.w,
backgroundColor: insuranceVM.isInsuranceExpired ? AppColors.primaryRedColor.withOpacity(0.1) : AppColors.successColor.withOpacity(0.1), backgroundColor:
insuranceVM.isInsuranceExpired ? AppColors.primaryRedColor.withOpacity(0.1) : AppColors.successColor.withOpacity(0.1),
labelPadding: EdgeInsetsDirectional.only(start: -4.w, end: 6.w), labelPadding: EdgeInsetsDirectional.only(start: -4.w, end: 6.w),
); );
}), }),
@ -381,9 +383,7 @@ class _MedicalFilePageState extends State<MedicalFilePage> {
width: hmgServicesVM.vitalSignCurrentPage == index ? 24.w : 8.w, width: hmgServicesVM.vitalSignCurrentPage == index ? 24.w : 8.w,
height: 8.h, height: 8.h,
decoration: BoxDecoration( decoration: BoxDecoration(
color: hmgServicesVM.vitalSignCurrentPage == index color: hmgServicesVM.vitalSignCurrentPage == index ? AppColors.primaryRedColor : AppColors.dividerColor,
? AppColors.primaryRedColor
: AppColors.dividerColor,
borderRadius: BorderRadius.circular(4.r), borderRadius: BorderRadius.circular(4.r),
), ),
), ),
@ -587,7 +587,8 @@ class _MedicalFilePageState extends State<MedicalFilePage> {
? Container( ? Container(
padding: EdgeInsets.all(12.w), padding: EdgeInsets.all(12.w),
width: MediaQuery.of(context).size.width, width: MediaQuery.of(context).size.width,
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 12.r, hasShadow: false), decoration:
RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 12.r, hasShadow: false),
child: Column( child: Column(
children: [ children: [
Utils.buildSvgWithAssets(icon: AppAssets.home_calendar_icon, width: 32.h, height: 32.h), Utils.buildSvgWithAssets(icon: AppAssets.home_calendar_icon, width: 32.h, height: 32.h),
@ -624,57 +625,58 @@ class _MedicalFilePageState extends State<MedicalFilePage> {
itemCount: myAppointmentsVM.patientAppointmentsHistoryList.length, itemCount: myAppointmentsVM.patientAppointmentsHistoryList.length,
itemBuilder: (context, index) { itemBuilder: (context, index) {
return AnimationConfiguration.staggeredList( return AnimationConfiguration.staggeredList(
position: index, position: index,
duration: const Duration(milliseconds: 500), duration: const Duration(milliseconds: 500),
child: SlideAnimation( child: SlideAnimation(
horizontalOffset: 100.0, horizontalOffset: 100.0,
child: FadeInAnimation( child: FadeInAnimation(
child: AnimatedContainer( child: AnimatedContainer(
duration: const Duration(milliseconds: 300), duration: const Duration(milliseconds: 300),
curve: Curves.easeInOut, curve: Curves.easeInOut,
child: MedicalFileAppointmentCard( child: MedicalFileAppointmentCard(
patientAppointmentHistoryResponseModel: myAppointmentsVM.patientAppointmentsHistoryList[index], patientAppointmentHistoryResponseModel: myAppointmentsVM.patientAppointmentsHistoryList[index],
myAppointmentsViewModel: myAppointmentsViewModel, myAppointmentsViewModel: myAppointmentsViewModel,
onRescheduleTap: () { onRescheduleTap: () {
openDoctorScheduleCalendar(myAppointmentsVM.patientAppointmentsHistoryList[index]); openDoctorScheduleCalendar(myAppointmentsVM.patientAppointmentsHistoryList[index]);
}, },
onAskDoctorTap: () async { onAskDoctorTap: () async {
LoaderBottomSheet.showLoader(loadingText: "Checking doctor availability...".needTranslation); LoaderBottomSheet.showLoader(loadingText: "Checking doctor availability...".needTranslation);
await myAppointmentsViewModel.isDoctorAvailable( await myAppointmentsViewModel.isDoctorAvailable(
projectID: myAppointmentsVM.patientAppointmentsHistoryList[index].projectID, projectID: myAppointmentsVM.patientAppointmentsHistoryList[index].projectID,
doctorId: myAppointmentsVM.patientAppointmentsHistoryList[index].doctorID, doctorId: myAppointmentsVM.patientAppointmentsHistoryList[index].doctorID,
clinicId: myAppointmentsVM.patientAppointmentsHistoryList[index].clinicID, clinicId: myAppointmentsVM.patientAppointmentsHistoryList[index].clinicID,
onSuccess: (value) async { onSuccess: (value) async {
if (value) { if (value) {
await myAppointmentsViewModel.getAskDoctorRequestTypes(onSuccess: (val) { await myAppointmentsViewModel.getAskDoctorRequestTypes(onSuccess: (val) {
LoaderBottomSheet.hideLoader();
showCommonBottomSheetWithoutHeight(
context,
title: LocaleKeys.askDoctor.tr(context: context),
child: AskDoctorRequestTypeSelect(
askDoctorRequestTypeList: myAppointmentsViewModel.askDoctorRequestTypeList,
myAppointmentsViewModel: myAppointmentsViewModel,
patientAppointmentHistoryResponseModel:
myAppointmentsVM.patientAppointmentsHistoryList[index],
),
callBackFunc: () {},
isFullScreen: false,
isCloseButtonVisible: true,
);
});
} else {
LoaderBottomSheet.hideLoader(); LoaderBottomSheet.hideLoader();
showCommonBottomSheetWithoutHeight( print("Doctor is not available");
context, }
title: LocaleKeys.askDoctor.tr(context: context), },
child: AskDoctorRequestTypeSelect( onError: (_) {
askDoctorRequestTypeList: myAppointmentsViewModel.askDoctorRequestTypeList,
myAppointmentsViewModel: myAppointmentsViewModel,
patientAppointmentHistoryResponseModel: myAppointmentsVM.patientAppointmentsHistoryList[index],
),
callBackFunc: () {},
isFullScreen: false,
isCloseButtonVisible: true,
);
});
} else {
LoaderBottomSheet.hideLoader(); LoaderBottomSheet.hideLoader();
print("Doctor is not available"); },
} );
}, },
onError: (_) { ),
LoaderBottomSheet.hideLoader();
},
);
},
), ),
), ),
), ));
));
}, },
separatorBuilder: (BuildContext cxt, int index) => SizedBox(width: 12.h), separatorBuilder: (BuildContext cxt, int index) => SizedBox(width: 12.h),
), ),
@ -733,116 +735,125 @@ class _MedicalFilePageState extends State<MedicalFilePage> {
child: Column( child: Column(
children: [ children: [
ListView.separated( ListView.separated(
itemCount: prescriptionVM.patientPrescriptionOrders.length <= 2 ? prescriptionVM.patientPrescriptionOrders.length : 2, itemCount:
prescriptionVM.patientPrescriptionOrders.length <= 2 ? prescriptionVM.patientPrescriptionOrders.length : 2,
shrinkWrap: true, shrinkWrap: true,
padding: EdgeInsets.only(left: 0, right: 8.w), padding: EdgeInsets.only(left: 0, right: 8.w),
physics: NeverScrollableScrollPhysics(), physics: NeverScrollableScrollPhysics(),
itemBuilder: (context, index) { itemBuilder: (context, index) {
return AnimationConfiguration.staggeredList( return AnimationConfiguration.staggeredList(
position: index, position: index,
duration: const Duration(milliseconds: 500), duration: const Duration(milliseconds: 500),
child: SlideAnimation( child: SlideAnimation(
verticalOffset: 100.0, verticalOffset: 100.0,
child: FadeInAnimation( child: FadeInAnimation(
child: Row( child: Row(
children: [ children: [
Image.network( Image.network(
prescriptionVM.patientPrescriptionOrders[index].doctorImageURL!, prescriptionVM.patientPrescriptionOrders[index].doctorImageURL!,
width: 40.w, width: 40.w,
height: 40.h, height: 40.h,
fit: BoxFit.cover, fit: BoxFit.cover,
).circle(100.r), ).circle(100.r),
SizedBox(width: 16.w), SizedBox(width: 16.w),
Expanded( Expanded(
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
prescriptionVM.patientPrescriptionOrders[index].doctorName!.toText16(isBold: true), prescriptionVM.patientPrescriptionOrders[index].doctorName!.toText16(isBold: true),
SizedBox(height: 4.h), SizedBox(height: 4.h),
Wrap( Wrap(
direction: Axis.horizontal, direction: Axis.horizontal,
spacing: 3.w, spacing: 3.w,
runSpacing: 4.w, runSpacing: 4.w,
children: [ children: [
AppCustomChipWidget(labelText: prescriptionVM.patientPrescriptionOrders[index].clinicDescription!), AppCustomChipWidget(
AppCustomChipWidget( labelText: prescriptionVM.patientPrescriptionOrders[index].clinicDescription!),
icon: AppAssets.doctor_calendar_icon, AppCustomChipWidget(
labelText: DateUtil.formatDateToDate( icon: AppAssets.doctor_calendar_icon,
DateUtil.convertStringToDate(prescriptionVM.patientPrescriptionOrders[index].appointmentDate), labelText: DateUtil.formatDateToDate(
false, DateUtil.convertStringToDate(
prescriptionVM.patientPrescriptionOrders[index].appointmentDate),
false,
),
), ),
), ],
], ),
), ],
], ),
), ),
), // SizedBox(width: 40.h),
// SizedBox(width: 40.h), Transform.flip(
Transform.flip( flipX: appState.isArabic(),
flipX: appState.isArabic(), child: Utils.buildSvgWithAssets(
child: Utils.buildSvgWithAssets( icon: AppAssets.forward_arrow_icon_small,
icon: AppAssets.forward_arrow_icon_small, width: 15.w, height: 15.h, fit: BoxFit.contain, iconColor: AppColors.textColor)), width: 15.w,
], height: 15.h,
).onPress(() { fit: BoxFit.contain,
prescriptionVM.setPrescriptionsDetailsLoading(); iconColor: AppColors.textColor)),
Navigator.of(context).push( ],
CustomPageRoute( ).onPress(() {
page: PrescriptionDetailPage(isFromAppointments: false, prescriptionsResponseModel: prescriptionVM.patientPrescriptionOrders[index]), prescriptionVM.setPrescriptionsDetailsLoading();
), Navigator.of(context).push(
); CustomPageRoute(
}), page: PrescriptionDetailPage(
), isFromAppointments: false,
)); 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( separatorBuilder: (BuildContext cxt, int index) => SizedBox(height: 16.h),
children: [ ),
Expanded( SizedBox(height: 16.h),
child: CustomButton( const Divider(color: AppColors.dividerColor),
text: "All Prescriptions".needTranslation, SizedBox(height: 16.h),
onPressed: () { Row(
Navigator.of(context).push( children: [
CustomPageRoute( Expanded(
page: PrescriptionsListPage(), child: CustomButton(
), text: "All Prescriptions".needTranslation,
); onPressed: () {
}, Navigator.of(context).push(
backgroundColor: AppColors.secondaryLightRedColor, CustomPageRoute(
borderColor: AppColors.secondaryLightRedColor, page: PrescriptionsListPage(),
textColor: AppColors.primaryRedColor, ),
fontSize: 12.f, );
fontWeight: FontWeight.w500, },
borderRadius: 12.r, backgroundColor: AppColors.secondaryLightRedColor,
height: 40.h, borderColor: AppColors.secondaryLightRedColor,
icon: AppAssets.requests, textColor: AppColors.primaryRedColor,
iconColor: AppColors.primaryRedColor, fontSize: 12.f,
iconSize: 16.w, fontWeight: FontWeight.w500,
), borderRadius: 12.r,
height: 40.h,
icon: AppAssets.requests,
iconColor: AppColors.primaryRedColor,
iconSize: 16.w,
), ),
SizedBox(width: 6.w), ),
Expanded( SizedBox(width: 6.w),
child: CustomButton( Expanded(
text: "All Medications".needTranslation, child: CustomButton(
onPressed: () {}, text: "All Medications".needTranslation,
backgroundColor: AppColors.secondaryLightRedColor, onPressed: () {},
borderColor: AppColors.secondaryLightRedColor, backgroundColor: AppColors.secondaryLightRedColor,
textColor: AppColors.primaryRedColor, borderColor: AppColors.secondaryLightRedColor,
fontSize: 12.f, textColor: AppColors.primaryRedColor,
fontWeight: FontWeight.w500, fontSize: 12.f,
borderRadius: 12.h, fontWeight: FontWeight.w500,
height: 40.h, borderRadius: 12.h,
icon: AppAssets.all_medications_icon, height: 40.h,
iconColor: AppColors.primaryRedColor, icon: AppAssets.all_medications_icon,
iconSize: 16.h, iconColor: AppColors.primaryRedColor,
), iconSize: 16.h,
), ),
], ),
), ],
], ),
],
), ),
), ),
).paddingSymmetrical(0.w, 0.h) ).paddingSymmetrical(0.w, 0.h)
@ -896,7 +907,10 @@ class _MedicalFilePageState extends State<MedicalFilePage> {
fit: BoxFit.cover, fit: BoxFit.cover,
).circle(100).toShimmer2(isShow: true, radius: 50.r), ).circle(100).toShimmer2(isShow: true, radius: 50.r),
SizedBox(height: 8.h), SizedBox(height: 8.h),
("Dr. John Smith Smith Smith").toString().toText12(fontWeight: FontWeight.w500, isCenter: true, maxLine: 2).toShimmer2(isShow: true), ("Dr. John Smith Smith Smith")
.toString()
.toText12(fontWeight: FontWeight.w500, isCenter: true, maxLine: 2)
.toShimmer2(isShow: true),
], ],
) )
: myAppointmentsVM.patientMyDoctorsList.isEmpty : myAppointmentsVM.patientMyDoctorsList.isEmpty
@ -923,58 +937,58 @@ class _MedicalFilePageState extends State<MedicalFilePage> {
shrinkWrap: true, shrinkWrap: true,
itemBuilder: (context, index) { itemBuilder: (context, index) {
return AnimationConfiguration.staggeredList( return AnimationConfiguration.staggeredList(
position: index, position: index,
duration: const Duration(milliseconds: 1000), duration: const Duration(milliseconds: 1000),
child: SlideAnimation( child: SlideAnimation(
horizontalOffset: 100.0, horizontalOffset: 100.0,
child: FadeInAnimation( child: FadeInAnimation(
child: SizedBox( child: SizedBox(
// width: 80.w, // width: 80.w,
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.w, width: 64.w,
height: 64.h, height: 64.h,
fit: BoxFit.cover, fit: BoxFit.cover,
).circle(100).toShimmer2(isShow: false, radius: 50.r), ).circle(100).toShimmer2(isShow: false, radius: 50.r),
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),
), ),
], ],
), ),
).onPress(() async { ).onPress(() async {
bookAppointmentsViewModel.setSelectedDoctor(DoctorsListResponseModel( bookAppointmentsViewModel.setSelectedDoctor(DoctorsListResponseModel(
clinicID: myAppointmentsVM.patientMyDoctorsList[index].clinicID, clinicID: myAppointmentsVM.patientMyDoctorsList[index].clinicID,
projectID: myAppointmentsVM.patientMyDoctorsList[index].projectID, projectID: myAppointmentsVM.patientMyDoctorsList[index].projectID,
doctorID: myAppointmentsVM.patientMyDoctorsList[index].doctorID, doctorID: myAppointmentsVM.patientMyDoctorsList[index].doctorID,
)); ));
LoaderBottomSheet.showLoader(); LoaderBottomSheet.showLoader();
await bookAppointmentsViewModel.getDoctorProfile(onSuccess: (dynamic respData) { await bookAppointmentsViewModel.getDoctorProfile(onSuccess: (dynamic respData) {
LoaderBottomSheet.hideLoader(); LoaderBottomSheet.hideLoader();
Navigator.of(context).push( Navigator.of(context).push(
CustomPageRoute( CustomPageRoute(
page: DoctorProfilePage(), page: DoctorProfilePage(),
), ),
); );
}, onError: (err) { }, onError: (err) {
LoaderBottomSheet.hideLoader(); LoaderBottomSheet.hideLoader();
showCommonBottomSheetWithoutHeight( showCommonBottomSheetWithoutHeight(
context, context,
child: Utils.getErrorWidget(loadingText: err), child: Utils.getErrorWidget(loadingText: err),
callBackFunc: () {}, callBackFunc: () {},
isFullScreen: false, isFullScreen: false,
isCloseButtonVisible: true, isCloseButtonVisible: true,
); );
}); });
}), }),
), ),
)); ));
}, },
separatorBuilder: (BuildContext cxt, int index) => SizedBox(width: 8.h), separatorBuilder: (BuildContext cxt, int index) => SizedBox(width: 8.h),
), ),
@ -1083,9 +1097,14 @@ class _MedicalFilePageState extends State<MedicalFilePage> {
text: "${LocaleKeys.updateInsurance.tr(context: context)} ${LocaleKeys.updateInsuranceSubtitle.tr(context: context)}", text: "${LocaleKeys.updateInsurance.tr(context: context)} ${LocaleKeys.updateInsuranceSubtitle.tr(context: context)}",
onPressed: () { onPressed: () {
insuranceViewModel.setIsInsuranceUpdateDetailsLoading(true); insuranceViewModel.setIsInsuranceUpdateDetailsLoading(true);
insuranceViewModel.getPatientInsuranceDetailsForUpdate( insuranceViewModel.getPatientInsuranceDetailsForUpdate(appState.getAuthenticatedUser()!.patientId.toString(),
appState.getAuthenticatedUser()!.patientId.toString(), appState.getAuthenticatedUser()!.patientIdentificationNo.toString()); appState.getAuthenticatedUser()!.patientIdentificationNo.toString());
showCommonBottomSheetWithoutHeight(context, child: PatientInsuranceCardUpdateCard(), callBackFunc: () {}, title: "", isCloseButtonVisible: false, isFullScreen: false); showCommonBottomSheetWithoutHeight(context,
child: PatientInsuranceCardUpdateCard(),
callBackFunc: () {},
title: "",
isCloseButtonVisible: false,
isFullScreen: false);
}, },
backgroundColor: AppColors.bgGreenColor.withOpacity(0.20), backgroundColor: AppColors.bgGreenColor.withOpacity(0.20),
borderColor: AppColors.bgGreenColor.withOpacity(0.0), borderColor: AppColors.bgGreenColor.withOpacity(0.0),
@ -1282,7 +1301,7 @@ class _MedicalFilePageState extends State<MedicalFilePage> {
svgIcon: AppAssets.blood_sugar_icon, svgIcon: AppAssets.blood_sugar_icon,
isLargeText: true, isLargeText: true,
iconSize: 36.w, iconSize: 36.w,
).onPress(() {}), ).onPress(() => context.navigateWithName(AppRoutes.healthTrackerDetailPage, arguments: HealthTrackerTypeEnum.bloodSugar)),
MedicalFileCard( MedicalFileCard(
label: "Blood Pressure".needTranslation, label: "Blood Pressure".needTranslation,
textColor: AppColors.blackColor, textColor: AppColors.blackColor,
@ -1290,7 +1309,7 @@ class _MedicalFilePageState extends State<MedicalFilePage> {
svgIcon: AppAssets.lab_result_icon, svgIcon: AppAssets.lab_result_icon,
isLargeText: true, isLargeText: true,
iconSize: 36.w, iconSize: 36.w,
).onPress(() {}), ).onPress(() => context.navigateWithName(AppRoutes.healthTrackerDetailPage, arguments: HealthTrackerTypeEnum.bloodPressure)),
MedicalFileCard( MedicalFileCard(
label: "Weight Tracker".needTranslation, label: "Weight Tracker".needTranslation,
textColor: AppColors.blackColor, textColor: AppColors.blackColor,
@ -1298,7 +1317,7 @@ class _MedicalFilePageState extends State<MedicalFilePage> {
svgIcon: AppAssets.weight_tracker_icon, svgIcon: AppAssets.weight_tracker_icon,
isLargeText: true, isLargeText: true,
iconSize: 36.w, iconSize: 36.w,
).onPress(() {}), ).onPress(() => context.navigateWithName(AppRoutes.healthTrackerDetailPage, arguments: HealthTrackerTypeEnum.weightTracker)),
], ],
).paddingSymmetrical(0.w, 0.0), ).paddingSymmetrical(0.w, 0.0),
SizedBox(height: 16.h), SizedBox(height: 16.h),
@ -1547,7 +1566,6 @@ class _MedicalFilePageState extends State<MedicalFilePage> {
], ],
), ),
SizedBox(height: 14.h), SizedBox(height: 14.h),
Container( Container(
padding: EdgeInsets.symmetric(horizontal: 8.w, vertical: 6.h), padding: EdgeInsets.symmetric(horizontal: 8.w, vertical: 6.h),
decoration: BoxDecoration( decoration: BoxDecoration(
@ -1585,7 +1603,6 @@ class _MedicalFilePageState extends State<MedicalFilePage> {
), ),
), ),
SizedBox(height: 8.h), SizedBox(height: 8.h),
Align( Align(
alignment: AlignmentDirectional.centerEnd, alignment: AlignmentDirectional.centerEnd,
child: Utils.buildSvgWithAssets( child: Utils.buildSvgWithAssets(
@ -1603,6 +1620,3 @@ class _MedicalFilePageState extends State<MedicalFilePage> {
); );
} }
} }

Loading…
Cancel
Save