From e3f5bb69accf1bdbd6f88645c68254f989d4a53c Mon Sep 17 00:00:00 2001 From: haroon amjad Date: Tue, 7 Apr 2026 21:34:09 +0300 Subject: [PATCH] Updates --- android/app/src/main/AndroidManifest.xml | 2 + android/app/src/main2/AndroidManifest.xml | 1 + assets/langs/ar-SA.json | 9 +- assets/langs/en-US.json | 9 +- lib/core/api_consts.dart | 4 +- lib/core/location_util.dart | 6 +- .../models/ui_models/vital_sign_ui_model.dart | 2 +- .../my_invoices/my_invoices_repo.dart | 40 +++++++++ .../my_invoices/my_invoices_view_model.dart | 29 ++++++- lib/generated/locale_keys.g.dart | 5 ++ .../appointment_details_page.dart | 28 +++--- ...mediate_livecare_pending_request_page.dart | 4 +- .../RRT/rrt_map_screen.dart | 50 +++++------ .../call_ambulance/call_ambulance_page.dart | 25 +++--- .../call_ambulance/tracking_screen.dart | 4 +- lib/presentation/home/landing_page.dart | 8 +- .../medical_file/medical_file_page.dart | 7 +- .../my_family/widget/family_cards.dart | 7 +- .../my_invoices/my_invoices_details_page.dart | 38 +++++++- .../prescriptions_list_page.dart | 12 ++- .../radiology/radiology_result_page.dart | 2 +- lib/widgets/attachment_options.dart | 87 ++++++++++++++++--- lib/widgets/custom_tab_bar.dart | 5 +- lib/widgets/image_picker.dart | 63 +++++++++++++- lib/widgets/map/gms_map.dart | 8 +- lib/widgets/map/map_utility_screen.dart | 19 ++-- 26 files changed, 371 insertions(+), 103 deletions(-) diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index d78abcc7..072d361f 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -50,6 +50,8 @@ android:name="android.permission.ACCESS_BACKGROUND_LOCATION" tools:node="remove" /> + + diff --git a/android/app/src/main2/AndroidManifest.xml b/android/app/src/main2/AndroidManifest.xml index c9e8c67e..535bd4ab 100644 --- a/android/app/src/main2/AndroidManifest.xml +++ b/android/app/src/main2/AndroidManifest.xml @@ -45,6 +45,7 @@ + >> getInvoiceDetails({required num appointmentNo, required num invoiceNo, required int projectID}); Future>> sendInvoiceEmail({required num appointmentNo, required int projectID}); + + Future>> downloadInvoice({required String setupId, required int invoiceNo, required int projectID}); } class MyInvoicesRepoImp implements MyInvoicesRepo { @@ -138,4 +140,42 @@ class MyInvoicesRepoImp implements MyInvoicesRepo { return Left(UnknownFailure(e.toString())); } } + + @override + Future> downloadInvoice({required String setupId, required int invoiceNo, required int projectID}) async { + Map mapDevice = { + "SetupID": setupId, + "ProjectID": projectID, + "InvoiceNo": invoiceNo, + }; + + try { + GenericApiModel? apiResponse; + Failure? failure; + await apiClient.post( + DOWNLOAD_INVOICE_PDF, + body: mapDevice, + onFailure: (error, statusCode, {messageStatus, failureType}) { + failure = failureType; + }, + onSuccess: (response, statusCode, {messageStatus, errorMessage}) { + try { + apiResponse = GenericApiModel( + messageStatus: messageStatus, + statusCode: statusCode, + errorMessage: null, + data: response["InvoiceReportPDFContent"], + ); + } catch (e) { + failure = DataParsingFailure(e.toString()); + } + }, + ); + if (failure != null) return Left(failure!); + if (apiResponse == null) return Left(ServerFailure("Unknown error")); + return Right(apiResponse!); + } catch (e) { + return Left(UnknownFailure(e.toString())); + } + } } diff --git a/lib/features/my_invoices/my_invoices_view_model.dart b/lib/features/my_invoices/my_invoices_view_model.dart index d51ea086..cd18026c 100644 --- a/lib/features/my_invoices/my_invoices_view_model.dart +++ b/lib/features/my_invoices/my_invoices_view_model.dart @@ -26,6 +26,8 @@ class MyInvoicesViewModel extends ChangeNotifier { TextEditingController filterSearchController = TextEditingController(); String? selectedFilterItem; + String? downloadInvoicePDFBase64 = ""; + MyInvoicesViewModel({required this.myInvoicesRepo, required this.errorHandlerService, required this.navServices}); setInvoicesListLoading() { @@ -68,7 +70,6 @@ class MyInvoicesViewModel extends ChangeNotifier { Future getInvoiceDetails({required num appointmentNo, required num invoiceNo, required int projectID, Function(dynamic)? onSuccess, Function(String)? onError}) async { final result = await myInvoicesRepo.getInvoiceDetails(appointmentNo: appointmentNo, invoiceNo: invoiceNo, projectID: projectID); - result.fold( (failure) async { isInvoiceDetailsLoading = false; @@ -93,6 +94,32 @@ class MyInvoicesViewModel extends ChangeNotifier { ); } + Future downloadInvoicePDF({required String setupId, required int invoiceNo, required int projectID, Function(dynamic)? onSuccess, Function(String)? onError}) async { + final result = await myInvoicesRepo.downloadInvoice(setupId: setupId, invoiceNo: invoiceNo, projectID: projectID); + + result.fold( + (failure) async { + if (onError != null) { + onError(failure.message); + } + }, + (apiResponse) { + if (apiResponse.messageStatus == 2) { + // dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {}); + } else if (apiResponse.messageStatus == 1) { + if (apiResponse.data != null && apiResponse.data!.isNotEmpty) { + downloadInvoicePDFBase64 = apiResponse.data!; + } else { + downloadInvoicePDFBase64 = ""; + } + if (onSuccess != null) { + onSuccess(apiResponse); + } + } + }, + ); + } + Future sendInvoiceEmail({required num appointmentNo, required int projectID, Function(dynamic)? onSuccess, Function(String)? onError}) async { final result = await myInvoicesRepo.sendInvoiceEmail(appointmentNo: appointmentNo, projectID: projectID); diff --git a/lib/generated/locale_keys.g.dart b/lib/generated/locale_keys.g.dart index fcb69d2f..2a999ae7 100644 --- a/lib/generated/locale_keys.g.dart +++ b/lib/generated/locale_keys.g.dart @@ -1676,5 +1676,10 @@ abstract class LocaleKeys { static const satelliteMapType = 'satelliteMapType'; static const terrainMapType = 'terrainMapType'; static const hybridMapType = 'hybridMapType'; + static const openCamera = 'openCamera'; + static const openGallery = 'openGallery'; + static const openFiles = 'openFiles'; + static const generateAiAnalysisRadResult = 'generateAiAnalysisRadResult'; + static const grantLocationPermission = 'grantLocationPermission'; } diff --git a/lib/presentation/appointments/appointment_details_page.dart b/lib/presentation/appointments/appointment_details_page.dart index fc5d766a..10f616e8 100644 --- a/lib/presentation/appointments/appointment_details_page.dart +++ b/lib/presentation/appointments/appointment_details_page.dart @@ -622,19 +622,21 @@ class _AppointmentDetailsPageState extends State { iconSize: 36.w, isLocked: !(myAppointmentsVM.appointmentRatedResponseModel!.isAppointmentRated ?? true), ).onPress(() { - showCommonBottomSheetWithoutHeight( - context, - title: LocaleKeys.doctorRating.tr(context: context), - isCloseButtonVisible: true, - child: StatefulBuilder( - builder: (context, setState) { - return AppointmentRatingWidget( - patientAppointmentHistoryResponseModel: widget.patientAppointmentHistoryResponseModel, - ); - }, - ), - isFullScreen: false, - ); + if(!(myAppointmentsVM.appointmentRatedResponseModel!.isAppointmentRated ?? true)) { + showCommonBottomSheetWithoutHeight( + context, + title: LocaleKeys.doctorRating.tr(context: context), + isCloseButtonVisible: true, + child: StatefulBuilder( + builder: (context, setState) { + return AppointmentRatingWidget( + patientAppointmentHistoryResponseModel: widget.patientAppointmentHistoryResponseModel, + ); + }, + ), + isFullScreen: false, + ); + } }), ], ); diff --git a/lib/presentation/book_appointment/livecare/immediate_livecare_pending_request_page.dart b/lib/presentation/book_appointment/livecare/immediate_livecare_pending_request_page.dart index 8b1e1d54..7af1c4e6 100644 --- a/lib/presentation/book_appointment/livecare/immediate_livecare_pending_request_page.dart +++ b/lib/presentation/book_appointment/livecare/immediate_livecare_pending_request_page.dart @@ -75,7 +75,7 @@ class _ImmediateLiveCarePendingRequestPageState extends State().bottomSheetType == - BottomSheetType.FIXED, - child: Padding( - padding: EdgeInsetsDirectional.only(end: 8.h, bottom: 68.h), - child: DecoratedBox( - decoration: RoundedRectangleBorder().toSmoothCornerDecoration( - color: AppColors.whiteColor, borderRadius: 12.h), - child: Utils.buildSvgWithAssets( - icon: AppAssets.locate_me, width: 24.h, height: 24.h) - .paddingAll(12.h) - .onPress(() { - context - .read() - .moveToCurrentLocation(); - }), - ), - ), - ), + // floatingActionButton: Visibility( + // visible: context.watch().bottomSheetType == + // BottomSheetType.FIXED, + // child: Padding( + // padding: EdgeInsetsDirectional.only(end: 8.h, bottom: 68.h), + // child: DecoratedBox( + // decoration: RoundedRectangleBorder().toSmoothCornerDecoration( + // color: AppColors.whiteColor, borderRadius: 12.h), + // child: Container() + // // Utils.buildSvgWithAssets( + // // icon: AppAssets.locate_me, width: 24.h, height: 24.h) + // // .paddingAll(12.h) + // // .onPress(() { + // // context + // // .read() + // // .moveToCurrentLocation(); + // // }), + // ), + // ), + // ), bottomSheet: ExpandableBottomSheet( bottomSheetType: context.watch().bottomSheetType, @@ -73,6 +74,7 @@ class RrtMapScreen extends StatelessWidget { inputController: context.read().gmsController, showCenterMarker: true, + bottomPaddingHeight: MediaQuery.of(context).size.height * 0.3, ) else HMSMap( @@ -189,10 +191,7 @@ class RrtMapScreen extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, spacing: 16.h, children: [ - hospitalAndPickUpSection(context), - - ], ).paddingOnly(top: 24.h, bottom: 32.h,left: 24.h, right: 24.h), @@ -227,9 +226,8 @@ class RrtMapScreen extends StatelessWidget { shrinkWrap: true, itemCount: 3, itemBuilder: (__, index) { - if (index == - 2) // todo means the end of the list so handle as per the viewmodel - { + if (index == 2) // todo means the end of the list so handle as per the viewmodel + { return CustomButton( height: 40.h, backgroundColor: AppColors.lightRedButtonColor, @@ -243,7 +241,7 @@ class RrtMapScreen extends StatelessWidget { return AddressItem( isSelected: index == 0, address: - "Flat No 301, Building No 12, Palm Spring Apartment, Sector 45, Gurugram, Haryana 122003", + "", title: index == 0 ? LocaleKeys.home.tr() : LocaleKeys.work.tr(), onTap: () {}, ); diff --git a/lib/presentation/emergency_services/call_ambulance/call_ambulance_page.dart b/lib/presentation/emergency_services/call_ambulance/call_ambulance_page.dart index 16f6ea14..a1b1839f 100644 --- a/lib/presentation/emergency_services/call_ambulance/call_ambulance_page.dart +++ b/lib/presentation/emergency_services/call_ambulance/call_ambulance_page.dart @@ -33,18 +33,18 @@ class CallAmbulancePage extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( - floatingActionButton: Visibility( - visible: context.watch().bottomSheetType == BottomSheetType.FIXED, - child: Padding( - padding: EdgeInsetsDirectional.only(end: 8.h, bottom: 68.h), - child: DecoratedBox( - decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 12.h), - child: Utils.buildSvgWithAssets(icon: AppAssets.locate_me, width: 24.h, height: 24.h).paddingAll(12.h).onPress(() { - context.read().moveToCurrentLocation(); - }), - ), - ), - ), + // floatingActionButton: Visibility( + // visible: context.watch().bottomSheetType == BottomSheetType.FIXED, + // child: Padding( + // padding: EdgeInsetsDirectional.only(end: 8.h, bottom: 68.h), + // child: DecoratedBox( + // decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 12.h), + // child: Utils.buildSvgWithAssets(icon: AppAssets.locate_me, width: 24.h, height: 24.h).paddingAll(12.h).onPress(() { + // context.read().moveToCurrentLocation(); + // }), + // ), + // ), + // ), bottomSheet: Column( mainAxisSize: MainAxisSize.min, children: [ @@ -67,6 +67,7 @@ class CallAmbulancePage extends StatelessWidget { myLocationEnabled: true, inputController: context.read().gmsController, showCenterMarker: true, + bottomPaddingHeight: MediaQuery.of(context).size.height * 0.42, ) else HMSMap( diff --git a/lib/presentation/emergency_services/call_ambulance/tracking_screen.dart b/lib/presentation/emergency_services/call_ambulance/tracking_screen.dart index abe9c81b..0f4c587b 100644 --- a/lib/presentation/emergency_services/call_ambulance/tracking_screen.dart +++ b/lib/presentation/emergency_services/call_ambulance/tracking_screen.dart @@ -253,7 +253,9 @@ class TrackingScreen extends StatelessWidget { }, currentLocation: context.read().getGMSLocation(), - onCameraMoved: (value) => context.read().handleGMSMapCameraMoved(value)); + onCameraMoved: (value) => context.read().handleGMSMapCameraMoved(value), + bottomPaddingHeight: MediaQuery.of(context).size.height * 0.2, + ); } else { return HMSMap( myLocationEnabled: false, diff --git a/lib/presentation/home/landing_page.dart b/lib/presentation/home/landing_page.dart index be1852ad..7ce46906 100644 --- a/lib/presentation/home/landing_page.dart +++ b/lib/presentation/home/landing_page.dart @@ -1050,7 +1050,7 @@ class _LandingPageState extends State { color: AppColors.whiteColor, borderRadius: 20.r, hasShadow: true, - side: BorderSide(color: AppColors.ratingColorYellow, width: 3.h), + // side: BorderSide(color: AppColors.ratingColorYellow, width: 3.h), ), child: Padding( padding: EdgeInsets.all(16.h), @@ -1071,7 +1071,11 @@ class _LandingPageState extends State { ), CustomButton( text: LocaleKeys.viewDetails.tr(context: context), - onPressed: () {}, + onPressed: () { + Navigator.of(context).push( + CustomPageRoute(page: ImmediateLiveCarePendingRequestPage()), + ); + }, backgroundColor: AppColors.warningColorYellow.withValues(alpha: 0.20), textColor: AppColors.alertColor, borderColor: AppColors.infoBannerBgColor, diff --git a/lib/presentation/medical_file/medical_file_page.dart b/lib/presentation/medical_file/medical_file_page.dart index 246500d7..e089c057 100644 --- a/lib/presentation/medical_file/medical_file_page.dart +++ b/lib/presentation/medical_file/medical_file_page.dart @@ -242,7 +242,12 @@ class _MedicalFilePageState extends State { Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Image.asset(appState.getAuthenticatedUser()?.gender == 1 ? AppAssets.maleImg : AppAssets.femaleImg, width: 56.w, height: 56.h), + Image.asset( + (appState.getAuthenticatedUser()?.gender == 1 + ? ((appState.getAuthenticatedUser()?.age ?? 0) < 7 ? AppAssets.babyBoyImg : AppAssets.maleImg) + : ((appState.getAuthenticatedUser()?.age ?? 0) < 7 ? AppAssets.babyGirlImg : AppAssets.femaleImg)), + width: 56.w, + height: 56.h), SizedBox(width: 8.w), Column( crossAxisAlignment: CrossAxisAlignment.start, diff --git a/lib/presentation/my_family/widget/family_cards.dart b/lib/presentation/my_family/widget/family_cards.dart index bb1cdb1e..39344f30 100644 --- a/lib/presentation/my_family/widget/family_cards.dart +++ b/lib/presentation/my_family/widget/family_cards.dart @@ -176,7 +176,12 @@ class _FamilyCardsState extends State { Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Image.asset(appState.getAuthenticatedUser()?.gender == 1 ? AppAssets.maleImg : AppAssets.femaleImg, width: 56.w, height: 56.h), + Image.asset( + (appState.getAuthenticatedUser()?.gender == 1 + ? ((appState.getAuthenticatedUser()?.age ?? 0) < 7 ? AppAssets.babyBoyImg : AppAssets.maleImg) + : ((appState.getAuthenticatedUser()?.age ?? 0) < 7 ? AppAssets.babyGirlImg : AppAssets.femaleImg)), + width: 56.w, + height: 56.h), SizedBox(width: 8.w), Column( crossAxisAlignment: CrossAxisAlignment.start, diff --git a/lib/presentation/my_invoices/my_invoices_details_page.dart b/lib/presentation/my_invoices/my_invoices_details_page.dart index a795fa01..62e5a336 100644 --- a/lib/presentation/my_invoices/my_invoices_details_page.dart +++ b/lib/presentation/my_invoices/my_invoices_details_page.dart @@ -18,6 +18,7 @@ import 'package:hmg_patient_app_new/widgets/appbar/collapsing_list_view.dart'; import 'package:hmg_patient_app_new/widgets/chip/app_custom_chip_widget.dart'; import 'package:hmg_patient_app_new/widgets/common_bottom_sheet.dart'; import 'package:hmg_patient_app_new/widgets/loader/bottomsheet_loader.dart'; +import 'package:open_filex/open_filex.dart'; import 'package:provider/provider.dart'; import 'dart:ui' as ui; @@ -47,10 +48,39 @@ class _MyInvoicesDetailsPageState extends State { title: LocaleKeys.invoiceDetails.tr(context: context), downloadInvoice: Utils.isVidaPlusProject(widget.getInvoiceDetailsResponseModel.projectID ?? 0) ? null : () { LoaderBottomSheet.showLoader(loadingText: LocaleKeys.loadingText.tr(context: context)); - - - - }, + myInvoicesViewModel.downloadInvoicePDF( + setupId: widget.getInvoicesListResponseModel.setupId!, + invoiceNo: widget.getInvoicesListResponseModel.invoiceNo!, + projectID: widget.getInvoicesListResponseModel.projectID!, + onError: (err) { + LoaderBottomSheet.hideLoader(); + showCommonBottomSheetWithoutHeight( + context, + child: Utils.getErrorWidget(loadingText: err), + callBackFunc: () {}, + isFullScreen: false, + isCloseButtonVisible: true, + ); + }, + onSuccess: (value) async { + LoaderBottomSheet.hideLoader(); + if (myInvoicesViewModel.downloadInvoicePDFBase64!.isNotEmpty) { + String path = await Utils.createFileFromString(myInvoicesViewModel.downloadInvoicePDFBase64!, "pdf"); + try { + OpenFilex.open(path); + } catch (ex) { + showCommonBottomSheetWithoutHeight( + context, + child: Utils.getErrorWidget(loadingText: "Cannot open file"), + callBackFunc: () {}, + isFullScreen: false, + isCloseButtonVisible: true, + ); + } + } + }, + ); + }, sendEmail: Utils.isVidaPlusProject(widget.getInvoiceDetailsResponseModel.projectID ?? 0) ? () async { LoaderBottomSheet.showLoader(loadingText: LocaleKeys.sendingEmailPleaseWait.tr(context: context)); await myInvoicesViewModel.sendInvoiceEmail( diff --git a/lib/presentation/prescriptions/prescriptions_list_page.dart b/lib/presentation/prescriptions/prescriptions_list_page.dart index 21fea5d2..b88eec30 100644 --- a/lib/presentation/prescriptions/prescriptions_list_page.dart +++ b/lib/presentation/prescriptions/prescriptions_list_page.dart @@ -543,7 +543,17 @@ class _PrescriptionsListPageState extends State { // ], // ), // ), - ), + ).onPress(() { + model.setPrescriptionsDetailsLoading(); + Navigator.of(context).push( + CustomPageRoute( + page: PrescriptionDetailPage( + prescriptionsResponseModel: model.patientPrescriptionOrders[index], + isFromAppointments: false, + ), + ), + ); + }), ), ), ) diff --git a/lib/presentation/radiology/radiology_result_page.dart b/lib/presentation/radiology/radiology_result_page.dart index 713fbda0..bb305c32 100644 --- a/lib/presentation/radiology/radiology_result_page.dart +++ b/lib/presentation/radiology/radiology_result_page.dart @@ -207,7 +207,7 @@ class _RadiologyResultPageState extends State { padding: EdgeInsets.only(right: 4.w, left: 4.w), child: Utils.buildSvgWithAssets(icon: AppAssets.aiOverView, width: 16.h, height: 16.h, iconColor: Colors.white), ), - LocaleKeys.generateAiAnalysisResult.tr(context: context).toText16(isBold: true, color: Colors.white) + LocaleKeys.generateAiAnalysisRadResult.tr(context: context).toText16(isBold: true, color: Colors.white) ], ), ).paddingSymmetrical(24.h, 12.h).onPress(() { diff --git a/lib/widgets/attachment_options.dart b/lib/widgets/attachment_options.dart index 116066bc..30a0da0c 100644 --- a/lib/widgets/attachment_options.dart +++ b/lib/widgets/attachment_options.dart @@ -1,5 +1,12 @@ +import 'package:easy_localization/easy_localization.dart'; +import 'package:hmg_patient_app_new/core/app_assets.dart'; +import 'package:hmg_patient_app_new/core/app_state.dart'; +import 'package:hmg_patient_app_new/core/dependencies.dart'; +import 'package:hmg_patient_app_new/core/utils/size_utils.dart'; +import 'package:hmg_patient_app_new/core/utils/utils.dart'; import 'package:hmg_patient_app_new/extensions/string_extensions.dart'; import 'package:hmg_patient_app_new/extensions/widget_extensions.dart'; +import 'package:hmg_patient_app_new/generated/locale_keys.g.dart'; import 'package:hmg_patient_app_new/theme/colors.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; @@ -12,28 +19,84 @@ class AttachmentOptions extends StatelessWidget { AttachmentOptions({Key? key, required this.onCameraTap, required this.onGalleryTap, required this.onFilesTap, this.showFilesOption = true}) : super(key: key); + late AppState? appState; + @override Widget build(BuildContext context) { + appState = getIt.get(); return SizedBox( width: double.infinity, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - "Upload Attachment".toSectionHeading(), - "Select from gallery or open camera".toText11(isBold: true), - GridView( - gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 3, childAspectRatio: 105 / 105, crossAxisSpacing: 9, mainAxisSpacing: 9), - physics: const NeverScrollableScrollPhysics(), - padding: const EdgeInsets.only(top: 21, bottom: 14), - shrinkWrap: true, + // "Upload Attachment".toSectionHeading(), + // "Select from gallery or open camera".toText11(isBold: true), + checkInOptionCard( + AppAssets.ask_doctor_icon, + LocaleKeys.openCamera.tr(context: context), + "", + ).onPress(() { + onCameraTap(); + }), + SizedBox(height: 16.h), + checkInOptionCard( + AppAssets.ask_doctor_icon, + LocaleKeys.openGallery.tr(context: context), + "", + ).onPress(() { + onGalleryTap(); + }), + SizedBox(height: 16.h), + checkInOptionCard( + AppAssets.ask_doctor_icon, + LocaleKeys.openFiles.tr(context: context), + "", + ).onPress(() { + onFilesTap(); + }), + ], + ).paddingOnly(), + ); + } + + Widget checkInOptionCard(String icon, String title, String subTitle) { + return Container( + decoration: RoundedRectangleBorder().toSmoothCornerDecoration( + color: AppColors.whiteColor, + borderRadius: 20.r, + hasShadow: false, + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // Utils.buildSvgWithAssets(icon: icon, width: 24.h, height: 24.h, fit: BoxFit.fill, iconColor: AppColors.textColor), + // SizedBox(height: 16.h), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - itemView("open_camera.svg", "Open\nCamera", onCameraTap), - itemView("gallery.svg", "Upload from\nGallery", onGalleryTap), - if (showFilesOption) itemView("files.svg", "Upload from\nFiles", onFilesTap), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + title.toText16(isBold: true, color: AppColors.textColor), + // subTitle.toText12(isBold: true, color: AppColors.greyTextColor), + ], + ), + ), + Transform.flip( + flipX: appState!.isArabic(), + child: Utils.buildSvgWithAssets( + icon: AppAssets.forward_arrow_icon_small, + iconColor: AppColors.blackColor, + width: 18.h, + height: 13.h, + fit: BoxFit.contain, + ), + ), ], - ) + ), ], - ).paddingOnly(left: 21, right: 21, bottom: 21), + ).paddingAll(16.h), ); } diff --git a/lib/widgets/custom_tab_bar.dart b/lib/widgets/custom_tab_bar.dart index 13d0c13e..c2d5d537 100644 --- a/lib/widgets/custom_tab_bar.dart +++ b/lib/widgets/custom_tab_bar.dart @@ -127,10 +127,7 @@ class CustomTabBarState extends State { width: 18.w, iconColor: isSelected ? activeTextColor : inActiveTextColor, ), - tabBar.title.toText13( - weight: isSelected ? FontWeight.w600 : FontWeight.w600, - color: isSelected ? activeTextColor : inActiveTextColor, - letterSpacing: isSelected ? -0.3 : -0.1), + tabBar.title.toText13(color: isSelected ? activeTextColor : inActiveTextColor, letterSpacing: isSelected ? -0.3 : -0.1, isBold: true), ], )).onPress(() { setState(() { diff --git a/lib/widgets/image_picker.dart b/lib/widgets/image_picker.dart index eb3021f5..c6d35617 100644 --- a/lib/widgets/image_picker.dart +++ b/lib/widgets/image_picker.dart @@ -1,21 +1,24 @@ import 'dart:convert'; import 'dart:io'; +import 'package:easy_localization/easy_localization.dart'; import 'package:hmg_patient_app_new/extensions/string_extensions.dart'; +import 'package:hmg_patient_app_new/generated/locale_keys.g.dart'; import 'package:hmg_patient_app_new/theme/colors.dart'; import 'package:hmg_patient_app_new/widgets/attachment_options.dart'; import 'package:hmg_patient_app_new/widgets/bottom_sheet.dart'; import 'package:file_picker/file_picker.dart'; import 'package:flutter/material.dart'; +import 'package:hmg_patient_app_new/widgets/common_bottom_sheet.dart'; import 'package:image_picker/image_picker.dart'; final ImagePicker picker = ImagePicker(); class ImageOptions { static void showImageOptionsNew(BuildContext context, bool showFilesOption, Function(String, File) image) { - showMyBottomSheet( + showCommonBottomSheetWithoutHeight( context, - callBackFunc: () {}, + title: LocaleKeys.feedback.tr(), child: AttachmentOptions( showFilesOption: showFilesOption, onCameraTap: () async { @@ -66,7 +69,63 @@ class ImageOptions { image(result.files.first.path.toString(), files.first); }, ), + callBackFunc: () {}, + isFullScreen: false, ); + // showMyBottomSheet( + // context, + // callBackFunc: () {}, + // child: AttachmentOptions( + // showFilesOption: showFilesOption, + // onCameraTap: () async { + // if (Platform.isAndroid) { + // cameraImageAndroid(image); + // } else { + // File _image = File((await ImagePicker.platform.pickImage(source: ImageSource.camera, imageQuality: 20))?.path ?? ""); + // // XFile? media = await picker.pickMedia(); + // String? fileName = _image.path; + // var bytes = File(fileName!).readAsBytesSync(); + // String base64Encode = base64.encode(bytes); + // if (base64Encode != null) { + // image(base64Encode, _image); + // } + // } + // }, + // onGalleryTap: () async { + // if (Platform.isAndroid) { + // galleryImageAndroid(image); + // } else { + // File _image = File((await picker.pickMedia())?.path ?? ""); + // String fileName = _image.path; + // var bytes = File(fileName).readAsBytesSync(); + // String base64Encode = base64.encode(bytes); + // if (base64Encode != null) { + // image(base64Encode, _image); + // } + // } + // }, + // onFilesTap: () async { + // FilePickerResult? result = await FilePicker.platform.pickFiles( + // type: FileType.custom, + // allowedExtensions: [ + // 'jpg', + // 'jpeg ', + // 'pdf', + // 'txt', + // 'docx', + // 'doc', + // 'pptx', + // 'xlsx', + // 'png', + // 'rar', + // 'zip', + // ], + // ); + // List files = result!.paths.map((path) => File(path!)).toList(); + // image(result.files.first.path.toString(), files.first); + // }, + // ), + // ); } // static void showImageOptions(BuildContext context, Function(String, File) image) { diff --git a/lib/widgets/map/gms_map.dart b/lib/widgets/map/gms_map.dart index 7ffe6ac6..24f180cd 100644 --- a/lib/widgets/map/gms_map.dart +++ b/lib/widgets/map/gms_map.dart @@ -72,6 +72,7 @@ class GMSMap extends StatefulWidget { final bool myLocationEnabled; final bool showCenterMarker; final Completer? inputController; + final num bottomPaddingHeight; const GMSMap({ super.key, @@ -83,6 +84,7 @@ class GMSMap extends StatefulWidget { this.showCenterMarker = false, this.myLocationEnabled = true, this.inputController, + required this.bottomPaddingHeight, }); @override @@ -93,6 +95,7 @@ class _GMSMapState extends State { late Completer _controller; late MapType _selectedMapType; bool _showMapTypeSelector = false; + num bottomPaddingHeight = 0; /// All supported map types with display labels and icons final List<_MapTypeOption> _mapTypeOptions = [ @@ -145,7 +148,8 @@ class _GMSMapState extends State { mapType: _selectedMapType, zoomControlsEnabled: true, myLocationEnabled: widget.myLocationEnabled, - myLocationButtonEnabled: false, + myLocationButtonEnabled: true, + padding: EdgeInsets.only(bottom: double.parse(widget.bottomPaddingHeight.toString())), compassEnabled: widget.compassEnabled, initialCameraPosition: widget.currentLocation, onCameraMove: widget.onCameraMoved, @@ -163,7 +167,7 @@ class _GMSMapState extends State { Icons.location_pin, size: 36.h, color: AppColors.primaryRedColor, - ).paddingOnly(bottom: 24.h), + ).paddingOnly(bottom: double.parse((widget.bottomPaddingHeight + 25.h).toString())), ), // ── Map-type toggle button ────────────────────────────────────── diff --git a/lib/widgets/map/map_utility_screen.dart b/lib/widgets/map/map_utility_screen.dart index f5cf7f58..6c1d9e89 100644 --- a/lib/widgets/map/map_utility_screen.dart +++ b/lib/widgets/map/map_utility_screen.dart @@ -48,15 +48,15 @@ class MapUtilityScreen extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( - floatingActionButton: Padding( - padding: EdgeInsetsDirectional.only(end: 8.h, bottom: 68.h), - child: DecoratedBox( - decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 12.h), - child: Utils.buildSvgWithAssets(icon: AppAssets.locate_me, width: 24.h, height: 24.h).paddingAll(12.h).onPress(() { - context.read().moveToCurrentLocation(); - }), - ), - ), + // floatingActionButton: Padding( + // padding: EdgeInsetsDirectional.only(end: 8.h, bottom: 68.h), + // child: DecoratedBox( + // decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 12.h), + // child: Utils.buildSvgWithAssets(icon: AppAssets.locate_me, width: 24.h, height: 24.h).paddingAll(12.h).onPress(() { + // context.read().moveToCurrentLocation(); + // }), + // ), + // ), bottomSheet: FixedBottomSheet(context), body: Stack( children: [ @@ -68,6 +68,7 @@ class MapUtilityScreen extends StatelessWidget { myLocationEnabled: true, inputController: context.read().gmsController, showCenterMarker: true, + bottomPaddingHeight: MediaQuery.of(context).size.height * 0.2, ) else HMSMap(