Completed the HHC and CMC

pull/113/head
faizatflutter 2 months ago
parent 5e437e42a9
commit 8068de70cb

@ -513,12 +513,6 @@ var PATIENT_ER_INSERT_PRES_ORDER = 'Services/Patients.svc/REST/PatientER_InsertP
var BLOOD_DONATION_REGISTER_BLOOD_TYPE = 'Services/PatientVarification.svc/REST/BloodDonation_RegisterBloodType';
var ADD_USER_AGREEMENT_FOR_BLOOD_DONATION = 'Services/PatientVarification.svc/REST/AddUserAgreementForBloodDonation';
// HHC RC SERVICES
var HHC_GET_ALL_SERVICES_RC = "api/HHC/getallhhc";
var ADD_HHC_ORDER_RC = "api/HHC/add";
var GET_ALL_HHC_ORDERS_RC = 'api/hhc/list';
var UPDATE_HHC_ORDER_RC = 'api/hhc/update';
// RRT RC SERVICES
var ADD_RRT_ORDER_RC = "api/rrt/add";
var GET_ALL_RRT_ORDERS_RC = "api/rrt/list";
@ -858,3 +852,7 @@ class ApiConsts {
static final String appGeneralId = "Cs2020@2016\$2958";
static final String sessionID = 'TMRhVmkGhOsvamErw';
}
class ApiKeyConstants {
static final String googleMapsApiKey = 'AIzaSyB6TERnxIr0yJ3qG4ULBZbu0sAD4tGqtng';
}

@ -2,7 +2,7 @@ import 'dart:async';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:flutter_staggered_animations/flutter_staggered_animations.dart';
import 'package:hmg_patient_app_new/core/api_consts.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/utils/size_utils.dart';
@ -26,11 +26,7 @@ import 'package:hmg_patient_app_new/presentation/appointments/widgets/appointmen
import 'package:hmg_patient_app_new/presentation/appointments/widgets/ask_doctor_request_type_select.dart';
import 'package:hmg_patient_app_new/presentation/book_appointment/widgets/appointment_calendar.dart';
import 'package:hmg_patient_app_new/presentation/contact_us/feedback_page.dart';
import 'package:hmg_patient_app_new/presentation/lab/lab_orders_page.dart';
import 'package:hmg_patient_app_new/presentation/medical_file/widgets/lab_rad_card.dart';
import 'package:hmg_patient_app_new/presentation/prescriptions/prescription_detail_page.dart';
import 'package:hmg_patient_app_new/presentation/prescriptions/prescriptions_list_page.dart';
import 'package:hmg_patient_app_new/presentation/radiology/radiology_orders_page.dart';
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/buttons/custom_button.dart';
@ -208,7 +204,7 @@ class _AppointmentDetailsPageState extends State<AppointmentDetailsPage> {
borderRadius: BorderRadius.circular(24.r),
// Todo: what is this???? Api Key??? 😲
child: Image.network(
"https://maps.googleapis.com/maps/api/staticmap?center=${widget.patientAppointmentHistoryResponseModel.latitude},${widget.patientAppointmentHistoryResponseModel.longitude}&zoom=14&size=350x165&maptype=roadmap&markers=color:red%7C${widget.patientAppointmentHistoryResponseModel.latitude},${widget.patientAppointmentHistoryResponseModel.longitude}&key=AIzaSyB6TERnxIr0yJ3qG4ULBZbu0sAD4tGqtng",
"https://maps.googleapis.com/maps/api/staticmap?center=${widget.patientAppointmentHistoryResponseModel.latitude},${widget.patientAppointmentHistoryResponseModel.longitude}&zoom=14&size=350x165&maptype=roadmap&markers=color:red%7C${widget.patientAppointmentHistoryResponseModel.latitude},${widget.patientAppointmentHistoryResponseModel.longitude}&key=${ApiKeyConstants.googleMapsApiKey}",
fit: BoxFit.contain,
),
),
@ -286,17 +282,17 @@ class _AppointmentDetailsPageState extends State<AppointmentDetailsPage> {
)
// : SizedBox.shrink()
: GridView(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
crossAxisSpacing: 16.h,
mainAxisSpacing: 16.w,
mainAxisExtent: 115.h,
),
physics: NeverScrollableScrollPhysics(),
padding: EdgeInsets.zero,
shrinkWrap: true,
children: [
MedicalFileCard(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
crossAxisSpacing: 16.h,
mainAxisSpacing: 16.w,
mainAxisExtent: 115.h,
),
physics: NeverScrollableScrollPhysics(),
padding: EdgeInsets.zero,
shrinkWrap: true,
children: [
MedicalFileCard(
label: LocaleKeys.labResults.tr(context: context),
textColor: AppColors.blackColor,
backgroundColor: AppColors.whiteColor,
@ -385,13 +381,15 @@ class _AppointmentDetailsPageState extends State<AppointmentDetailsPage> {
);
Navigator.of(context).push(
CustomPageRoute(
page: PrescriptionDetailPage(isFromAppointments: true, prescriptionsResponseModel: patientPrescriptionsResponseModel),
page: PrescriptionDetailPage(
isFromAppointments: true, prescriptionsResponseModel: patientPrescriptionsResponseModel),
),
);
} else {
showCommonBottomSheetWithoutHeight(
context,
child: Utils.getErrorWidget(loadingText: "You don't have any prescriptions for this appointment.".needTranslation),
child: Utils.getErrorWidget(
loadingText: "You don't have any prescriptions for this appointment.".needTranslation),
callBackFunc: () {},
isFullScreen: false,
isCloseButtonVisible: true,
@ -412,11 +410,11 @@ class _AppointmentDetailsPageState extends State<AppointmentDetailsPage> {
// Navigator.of(context).push(
// CustomPageRoute(
// page: VaccineListPage(),
// ),
// );
}),
],
),
// ),
// );
}),
],
),
// Column(
// crossAxisAlignment: CrossAxisAlignment.start,
// children: [

@ -2,7 +2,6 @@ import 'dart:developer';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:hmg_patient_app_new/core/app_assets.dart';
import 'package:hmg_patient_app_new/core/app_state.dart';
import 'package:hmg_patient_app_new/core/dependencies.dart';
import 'package:hmg_patient_app_new/core/utils/size_utils.dart';
@ -22,6 +21,7 @@ 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/common_bottom_sheet.dart';
import 'package:hmg_patient_app_new/widgets/loader/bottomsheet_loader.dart';
import 'package:hmg_patient_app_new/widgets/map/location_map_widget.dart';
import 'package:maps_launcher/maps_launcher.dart';
import 'package:provider/provider.dart';
@ -155,100 +155,26 @@ class _CmcSelectionReviewPageState extends State<CmcSelectionReviewPage> {
}
Widget _buildHospitalMap(HospitalsModel selectedHospital) {
final String lat = selectedHospital.latitude ?? "0.0";
final String lng = selectedHospital.longitude ?? "0.0";
final String lat = ((selectedHospital.latitude == null || selectedHospital.latitude!.isEmpty) ? "0.0" : selectedHospital.latitude) ?? "0.0";
final String lng = ((selectedHospital.longitude == null || selectedHospital.longitude!.isEmpty) ? "0.0" : selectedHospital.longitude) ?? "0.0";
log("selectedHospital: $lng and $lat");
if (lat == "0.0" || lng == "0.0") return SizedBox.shrink();
final String staticMapUrl =
"https://maps.googleapis.com/maps/api/staticmap?center=$lat,$lng&zoom=16&size=600x300&maptype=roadmap&markers=color:red%7C$lat,$lng&key=AIzaSyCyDbWUM9d_sBUGIE8PcuShzPaqO08NSC8";
return Stack(
children: [
ClipRRect(
borderRadius: BorderRadius.circular(12.r),
child: Image.network(
staticMapUrl,
height: 200.h,
width: double.infinity,
fit: BoxFit.cover,
loadingBuilder: (context, child, loadingProgress) {
if (loadingProgress == null) return child;
return Container(
height: 200.h,
decoration: BoxDecoration(
color: AppColors.bgScaffoldColor,
borderRadius: BorderRadius.circular(12.r),
),
child: Center(
child: CircularProgressIndicator(
color: AppColors.primaryRedColor,
),
),
);
},
errorBuilder: (context, error, stackTrace) {
return Container(
height: 200.h,
decoration: BoxDecoration(
color: AppColors.bgScaffoldColor,
borderRadius: BorderRadius.circular(12.r),
),
child: Center(
child: Icon(
Icons.error_outline,
size: 48.h,
color: AppColors.greyTextColor,
),
),
);
},
),
),
Positioned(
bottom: 12.h,
right: 12.w,
child: InkWell(
onTap: () => _launchDirections(selectedHospital),
child: Container(
padding: EdgeInsets.symmetric(horizontal: 12.w, vertical: 8.h),
decoration: BoxDecoration(
color: AppColors.whiteColor,
borderRadius: BorderRadius.circular(1000.r),
boxShadow: [
BoxShadow(
color: Color.fromARGB(26, 0, 0, 0),
blurRadius: 8,
offset: Offset(0, 2),
),
],
),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Utils.buildSvgWithAssets(
icon: AppAssets.directions_icon,
width: 16.w,
height: 16.h,
),
SizedBox(width: 6.w),
Text(
"Get Directions".needTranslation,
style: TextStyle(
fontSize: 12.f,
fontWeight: FontWeight.w600,
color: AppColors.blackColor,
letterSpacing: -0.4,
),
),
],
),
),
),
),
],
final appState = getIt.get<AppState>();
final isArabic = appState.isArabic();
final hospitalName = isArabic ? (selectedHospital.nameN ?? selectedHospital.name ?? '') : (selectedHospital.name ?? '');
return LocationMapWidget(
latitude: double.parse(lat),
longitude: double.parse(lng),
address: hospitalName,
title: "Hospital Location".needTranslation,
showTitle: false,
showAddress: false,
padding: EdgeInsets.zero,
onDirectionsTap: () => _launchDirections(selectedHospital),
);
}

@ -13,9 +13,11 @@ import 'package:hmg_patient_app_new/features/hmg_services/models/resq_models/get
import 'package:hmg_patient_app_new/presentation/home_health_care/hhc_order_detail_page.dart';
import 'package:hmg_patient_app_new/presentation/home_health_care/hhc_selection_review_page.dart';
import 'package:hmg_patient_app_new/presentation/home_health_care/widgets/hhc_ui_selection_helper.dart';
import 'package:hmg_patient_app_new/services/navigation_service.dart';
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/buttons/custom_button.dart';
import 'package:hmg_patient_app_new/widgets/map/map_utility_screen.dart';
import 'package:hmg_patient_app_new/widgets/routes/custom_page_route.dart';
import 'package:provider/provider.dart';
import 'package:shimmer/shimmer.dart';
@ -78,6 +80,15 @@ class _HhcProceduresPageState extends State<HhcProceduresPage> {
}
final canCancel = order.statusId == 1 || order.statusId == 2;
final isArabic = getIt.get<AppState>().isArabic();
// Extract services from orderselectedservice
List<dynamic> selectedServices = [];
if (order.orderselectedservice != null) {
if (order.orderselectedservice is List) {
selectedServices = order.orderselectedservice as List;
}
}
return Container(
width: double.infinity,
@ -128,6 +139,85 @@ class _HhcProceduresPageState extends State<HhcProceduresPage> {
],
),
// Services List
if (selectedServices.isNotEmpty) ...[
SizedBox(height: 16.h),
Container(
padding: EdgeInsets.all(12.w),
decoration: BoxDecoration(
color: AppColors.bgScaffoldColor,
borderRadius: BorderRadius.circular(12.r),
border: Border.all(
color: AppColors.greyColor.withAlpha(51),
width: 1,
),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Icon(
Icons.medical_services_outlined,
size: 18.h,
color: AppColors.primaryRedColor,
),
SizedBox(width: 6.w),
"Requested Services".needTranslation.toText14(
weight: FontWeight.w600,
color: AppColors.blackColor,
),
],
),
SizedBox(height: 8.h),
...selectedServices.asMap().entries.map((entry) {
int index = entry.key;
var service = entry.value;
String serviceName = '';
if (service is Map) {
if (isArabic) {
serviceName = service['SelectedServiceNameAR']?.toString() ??
service['selectedServiceNameAR']?.toString() ??
service['SelectedServiceName']?.toString() ??
service['selectedServiceName']?.toString() ??
'';
} else {
serviceName = service['SelectedServiceName']?.toString() ?? service['selectedServiceName']?.toString() ?? '';
}
}
return Padding(
padding: EdgeInsets.only(top: index > 0 ? 6.h : 0),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
margin: EdgeInsets.only(top: 6.h),
width: 6.w,
height: 6.w,
decoration: BoxDecoration(
color: AppColors.primaryRedColor,
shape: BoxShape.circle,
),
),
SizedBox(width: 8.w),
Expanded(
child: serviceName.toText14(
color: AppColors.blackColor,
weight: FontWeight.w500,
maxlines: 3,
),
),
],
),
);
}).toList(),
],
),
),
],
SizedBox(height: 12.h),
// Info message
@ -206,36 +296,6 @@ class _HhcProceduresPageState extends State<HhcProceduresPage> {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(height: 8.h),
if (viewModel.selectedHhcServices.isNotEmpty) ...[
SizedBox(height: 16.h),
Container(
margin: EdgeInsets.symmetric(horizontal: 16.w),
padding: EdgeInsets.all(16.w),
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.greyLightColor,
borderRadius: 16.r,
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
"Selected Services".needTranslation.toText12(
color: AppColors.textColorLight,
fontWeight: FontWeight.w600,
),
"${viewModel.selectedHhcServices.length} service(s) selected".toText14(
isBold: true,
weight: FontWeight.bold,
),
],
),
],
),
),
],
SizedBox(height: 16.h),
Text(
'Select Services'.needTranslation,
@ -304,18 +364,35 @@ class _HhcProceduresPageState extends State<HhcProceduresPage> {
);
},
),
// Summary Section
],
);
},
);
}
void _proceedWithSelectedService() {
void _proceedWithSelectedService() async {
final navigationServices = getIt.get<NavigationService>();
final appState = getIt.get<AppState>();
final hmgServicesViewModel = context.read<HmgServicesViewModel>();
if (hmgServicesViewModel.selectedHhcServices.isNotEmpty) {
hmgServicesViewModel.setSelectedServiceForHhcOrder(hmgServicesViewModel.selectedHhcServices.first);
Navigator.of(context).pushReplacement(
bool result = await navigationServices.push(
CustomPageRoute(
page: MapUtilityScreen(
confirmButtonString: "Submit Request ".needTranslation,
titleString: "Select Location",
subTitleString: "Please select the location".needTranslation,
isGmsAvailable: appState.isGMSAvailable,
),
direction: AxisDirection.down),
);
if (!result) {
return;
}
Navigator.of(context).push(
CustomPageRoute(
page: HhcSelectionReviewPage(selectedServices: hmgServicesViewModel.selectedHhcServices),
direction: AxisDirection.left,
@ -359,16 +436,48 @@ class _HhcProceduresPageState extends State<HhcProceduresPage> {
if (pendingOrder == null && hmgServicesViewModel.selectedHhcServices.isNotEmpty) {
return SafeArea(
top: false,
child: Padding(
padding: EdgeInsets.only(left: 16.w, right: 16.w, top: 12.h),
child: CustomButton(
borderWidth: 0,
text: "Next".needTranslation,
onPressed: _proceedWithSelectedService,
textColor: AppColors.whiteColor,
borderRadius: 12.r,
borderColor: Colors.transparent,
padding: EdgeInsets.symmetric(vertical: 14.h),
child: Container(
color: AppColors.whiteColor,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
// Selected Services Summary Widget
Container(
margin: EdgeInsets.symmetric(horizontal: 16.w, vertical: 4.h),
padding: EdgeInsets.all(16.w),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
"Selected Services".needTranslation.toText12(
color: AppColors.textColorLight,
fontWeight: FontWeight.w600,
),
"${hmgServicesViewModel.selectedHhcServices.length} service(s) selected".toText14(
isBold: true,
weight: FontWeight.bold,
),
],
),
],
),
),
// Next Button
Padding(
padding: EdgeInsets.only(left: 16.w, right: 16.w),
child: CustomButton(
borderWidth: 0,
text: "Next".needTranslation,
onPressed: _proceedWithSelectedService,
textColor: AppColors.whiteColor,
borderRadius: 12.r,
borderColor: Colors.transparent,
padding: EdgeInsets.symmetric(vertical: 14.h),
),
),
],
),
),
);

@ -10,13 +10,14 @@ import 'package:hmg_patient_app_new/extensions/widget_extensions.dart';
import 'package:hmg_patient_app_new/features/hmg_services/hmg_services_view_model.dart';
import 'package:hmg_patient_app_new/features/hmg_services/models/req_models/cmc_create_new_order_req_model.dart';
import 'package:hmg_patient_app_new/features/hmg_services/models/resq_models/get_cmc_services_resp_model.dart';
import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/hospital_model.dart';
import 'package:hmg_patient_app_new/features/location/location_view_model.dart';
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
import 'package:hmg_patient_app_new/theme/colors.dart';
import 'package:hmg_patient_app_new/widgets/appbar/collapsing_list_view.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/loader/bottomsheet_loader.dart';
import 'package:hmg_patient_app_new/widgets/map/location_map_widget.dart';
import 'package:maps_launcher/maps_launcher.dart';
import 'package:provider/provider.dart';
@ -57,6 +58,8 @@ class _HhcSelectionReviewPageState extends State<HhcSelectionReviewPage> {
children: [
_buildSelectedServicesCard(isArabic),
SizedBox(height: 16.h),
_buildLocationMap(),
SizedBox(height: 16.h),
],
),
),
@ -104,6 +107,36 @@ class _HhcSelectionReviewPageState extends State<HhcSelectionReviewPage> {
);
}
Widget _buildLocationMap() {
final locationViewModel = getIt.get<LocationViewModel>();
final geocodeResponse = locationViewModel.geocodeResponse;
final mapCapturedLocation = locationViewModel.mapCapturedLocation;
// Check if we have location data
if (mapCapturedLocation == null || (mapCapturedLocation.lat == 0.0 && mapCapturedLocation.lng == 0.0)) {
return SizedBox.shrink();
}
final double lat = mapCapturedLocation.lat ?? 0.0;
final double lng = mapCapturedLocation.lng ?? 0.0;
if (lat == 0.0 || lng == 0.0) return SizedBox.shrink();
// Get address from geocode response
String address = "Selected Location".needTranslation;
if (geocodeResponse != null && geocodeResponse.results.isNotEmpty) {
address = geocodeResponse.results.first.formattedAddress;
}
return LocationMapWidget(
latitude: lat,
longitude: lng,
address: address,
title: "Service Location".needTranslation,
onDirectionsTap: () => _launchDirectionsToLocation(lat, lng, address),
);
}
Widget _buildBottomButton() {
return SafeArea(
top: false,
@ -133,16 +166,9 @@ class _HhcSelectionReviewPageState extends State<HhcSelectionReviewPage> {
);
}
void _launchDirections(HospitalsModel selectedHospital) {
final double lat = double.parse(selectedHospital.latitude ?? "0.0");
final double lng = double.parse(selectedHospital.longitude ?? "0.0");
void _launchDirectionsToLocation(double lat, double lng, String locationName) {
if (lat != 0.0 && lng != 0.0) {
MapsLauncher.launchCoordinates(
lat,
lng,
selectedHospital.name ?? "Hospital",
);
MapsLauncher.launchCoordinates(lat, lng, locationName);
}
}

@ -0,0 +1,199 @@
import 'package:flutter/material.dart';
import 'package:hmg_patient_app_new/core/api_consts.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/extensions/string_extensions.dart';
import 'package:hmg_patient_app_new/extensions/widget_extensions.dart';
import 'package:hmg_patient_app_new/theme/colors.dart';
import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart';
import 'package:maps_launcher/maps_launcher.dart';
/// A reusable location map widget that displays a static map with address and directions button
/// Can be used in any review screen (HHC, CMC, etc.)
class LocationMapWidget extends StatelessWidget {
/// The latitude coordinate of the location
final double latitude;
/// The longitude coordinate of the location
final double longitude;
/// The formatted address or location name to display
final String address;
/// The title to show above the map (e.g., "Service Location", "Hospital Location")
final String title;
/// The zoom level for the map (default: 14)
final int zoomLevel;
/// The size of the map image (default: 350x165)
final String mapSize;
/// Optional callback when directions button is pressed
/// If not provided, will use default MapsLauncher
final VoidCallback? onDirectionsTap;
/// Whether to show the address container (default: true)
final bool showAddress;
/// Whether to show the title (default: true)
final bool showTitle;
/// Custom map type (default: roadmap)
final String mapType;
final EdgeInsets? padding;
const LocationMapWidget({
super.key,
required this.latitude,
required this.longitude,
required this.address,
required this.title,
this.zoomLevel = 14,
this.mapSize = '350x165',
this.onDirectionsTap,
this.showAddress = true,
this.showTitle = true,
this.mapType = 'roadmap',
this.padding,
});
void _defaultLaunchDirections() {
if (latitude != 0.0 && longitude != 0.0) {
MapsLauncher.launchCoordinates(latitude, longitude, address);
}
}
@override
Widget build(BuildContext context) {
final String staticMapUrl =
"https://maps.googleapis.com/maps/api/staticmap?center=$latitude,$longitude&zoom=$zoomLevel&size=$mapSize&maptype=$mapType&markers=color:red%7C$latitude,$longitude&key=${ApiKeyConstants.googleMapsApiKey}";
return Container(
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.whiteColor,
borderRadius: 16.r,
),
padding: padding ?? EdgeInsets.all(16.w),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// Title
if (showTitle) ...[
Text(
title,
style: TextStyle(
fontSize: 16.f,
fontWeight: FontWeight.w700,
color: AppColors.blackColor,
letterSpacing: -0.5,
),
),
SizedBox(height: 12.h),
],
// Address display
if (showAddress) ...[
Container(
padding: EdgeInsets.symmetric(horizontal: 12.w, vertical: 14.h),
decoration: BoxDecoration(
color: AppColors.bgScaffoldColor,
borderRadius: BorderRadius.circular(12.r),
border: Border.all(
color: AppColors.greyColor.withAlpha(51),
width: 1,
),
),
child: Row(
children: [
Icon(Icons.location_on, color: AppColors.primaryRedColor, size: 20.h),
SizedBox(width: 8.w),
Expanded(
child: Text(
address,
style: TextStyle(
fontSize: 14.f,
fontWeight: FontWeight.w500,
color: AppColors.blackColor,
letterSpacing: -0.4,
),
maxLines: 2,
overflow: TextOverflow.ellipsis,
),
),
],
),
),
SizedBox(height: 16.h),
],
// Map display with bottom button overlay
Stack(
children: [
ClipRRect(
clipBehavior: Clip.hardEdge,
borderRadius: BorderRadius.circular(24.r),
child: Image.network(
staticMapUrl,
fit: BoxFit.contain,
loadingBuilder: (context, child, loadingProgress) {
if (loadingProgress == null) return child;
return Container(
height: 165.h,
decoration: BoxDecoration(
color: AppColors.bgScaffoldColor,
borderRadius: BorderRadius.circular(24.r),
),
child: Center(
child: CircularProgressIndicator(
color: AppColors.primaryRedColor,
),
),
);
},
errorBuilder: (context, error, stackTrace) {
return Container(
height: 165.h,
decoration: BoxDecoration(
color: AppColors.bgScaffoldColor,
borderRadius: BorderRadius.circular(24.r),
),
child: Center(
child: Icon(
Icons.error_outline,
size: 48.h,
color: AppColors.greyTextColor,
),
),
);
},
),
),
Positioned(
bottom: 0,
child: SizedBox(
width: MediaQuery.of(context).size.width * 0.785,
child: CustomButton(
text: "Get Directions".needTranslation,
onPressed: onDirectionsTap ?? _defaultLaunchDirections,
backgroundColor: AppColors.textColor.withValues(alpha: 0.8),
borderColor: AppColors.textColor.withValues(alpha: 0.01),
textColor: AppColors.whiteColor,
fontSize: 14.f,
fontWeight: FontWeight.w500,
borderRadius: 12.r,
padding: EdgeInsets.symmetric(horizontal: 10.w),
height: 40.h,
icon: AppAssets.directions_icon,
iconColor: AppColors.whiteColor,
iconSize: 14.h,
).paddingAll(12.h),
),
),
],
),
],
),
);
}
}

@ -1,29 +1,13 @@
import 'dart:io';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:hmg_patient_app_new/core/app_assets.dart';
import 'package:hmg_patient_app_new/core/app_export.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/emergency_services/emergency_services_view_model.dart';
import 'package:hmg_patient_app_new/features/emergency_services/models/AmbulanceCallingPlace.dart';
import 'package:hmg_patient_app_new/features/location/GeocodeResponse.dart';
import 'package:hmg_patient_app_new/features/location/PlaceDetails.dart';
import 'package:hmg_patient_app_new/features/location/PlacePrediction.dart';
import 'package:hmg_patient_app_new/features/location/location_view_model.dart';
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
import 'package:hmg_patient_app_new/presentation/appointments/widgets/appointment_doctor_card.dart';
import 'package:hmg_patient_app_new/presentation/emergency_services/call_ambulance/widgets/AddressItem.dart';
import 'package:hmg_patient_app_new/presentation/emergency_services/call_ambulance/widgets/HospitalBottomSheetBody.dart';
import 'package:hmg_patient_app_new/presentation/emergency_services/call_ambulance/widgets/appointment_bottom_sheet.dart' show AppointmentBottomSheet;
import 'package:hmg_patient_app_new/presentation/emergency_services/widgets/location_input_bottom_sheet.dart';
import 'package:hmg_patient_app_new/theme/colors.dart';
import 'package:hmg_patient_app_new/widgets/CustomSwitch.dart';
import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart';
import 'package:hmg_patient_app_new/widgets/expandable_bottom_sheet/ExpandableBottomSheet.dart';
import 'package:hmg_patient_app_new/widgets/expandable_bottom_sheet/model/BottomSheetType.dart';
import 'package:hmg_patient_app_new/widgets/input_widget.dart';
import 'package:hmg_patient_app_new/widgets/map/HMSMap.dart';
import 'package:hmg_patient_app_new/widgets/map/gms_map.dart';
@ -42,14 +26,22 @@ import '../../../widgets/common_bottom_sheet.dart';
/// it results [true] if the user clicks on the submit button
/// and [false] if the user closes the screen without giving the consent to proceed for the request
class MapUtilityScreen extends StatelessWidget {
final String confirmButtonString;
final String titleString;
final String subTitleString;
final bool isGmsAvailable;
final VoidCallback? onCrossClicked;
final VoidCallback? onSubmitted;
const MapUtilityScreen({super.key, required this.confirmButtonString, required this.titleString, required this.subTitleString, required this.isGmsAvailable, this.onCrossClicked});
const MapUtilityScreen({
super.key,
required this.confirmButtonString,
required this.titleString,
required this.subTitleString,
required this.isGmsAvailable,
this.onCrossClicked,
this.onSubmitted,
});
@override
Widget build(BuildContext context) {
@ -57,15 +49,9 @@ class MapUtilityScreen extends StatelessWidget {
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<LocationViewModel>()
.moveToCurrentLocation();
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<LocationViewModel>().moveToCurrentLocation();
}),
),
),
@ -74,38 +60,26 @@ class MapUtilityScreen extends StatelessWidget {
children: [
if (isGmsAvailable)
GMSMap(
currentLocation:
context.read<LocationViewModel>().getGMSLocation(),
onCameraMoved: (value) => context
.read<LocationViewModel>()
.handleGMSMapCameraMoved(value),
onCameraIdle:
context.read<LocationViewModel>().handleOnCameraIdle,
currentLocation: context.read<LocationViewModel>().getGMSLocation(),
onCameraMoved: (value) => context.read<LocationViewModel>().handleGMSMapCameraMoved(value),
onCameraIdle: context.read<LocationViewModel>().handleOnCameraIdle,
myLocationEnabled: true,
inputController:
context.read<LocationViewModel>().gmsController,
inputController: context.read<LocationViewModel>().gmsController,
showCenterMarker: true,
)
else
HMSMap(
currentLocation:
context.read<LocationViewModel>().getHMSLocation(),
onCameraMoved: (value) => context
.read<LocationViewModel>()
.handleHMSMapCameraMoved(value),
onCameraIdle:
context.read<LocationViewModel>().handleOnCameraIdle,
currentLocation: context.read<LocationViewModel>().getHMSLocation(),
onCameraMoved: (value) => context.read<LocationViewModel>().handleHMSMapCameraMoved(value),
onCameraIdle: context.read<LocationViewModel>().handleOnCameraIdle,
myLocationEnabled: false,
inputController:
context.read<LocationViewModel>().hmsController,
inputController: context.read<LocationViewModel>().hmsController,
showCenterMarker: true,
),
Align(
alignment: AlignmentDirectional.topStart,
child: Utils.buildSvgWithAssets(
icon: AppAssets.closeBottomNav, width: 32.h, height: 32.h)
.onPress(() {
onCrossClicked?.call();
child: Utils.buildSvgWithAssets(icon: AppAssets.closeBottomNav, width: 32.h, height: 32.h).onPress(() {
onCrossClicked?.call();
// context
// .read<EmergencyServicesViewModel>()
// .flushPickupInformation();
@ -120,8 +94,7 @@ class MapUtilityScreen extends StatelessWidget {
Widget FixedBottomSheet(BuildContext context) {
return GestureDetector(
onVerticalDragUpdate: (details){
},
onVerticalDragUpdate: (details) {},
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.end,
@ -149,20 +122,23 @@ class MapUtilityScreen extends StatelessWidget {
spacing: 4.h,
children: [
titleString.toText21(
weight: FontWeight.w600,
color: AppColors.textColor,
),
weight: FontWeight.w600,
color: AppColors.textColor,
),
subTitleString.needTranslation.toText12(
fontWeight: FontWeight.w500,
color: AppColors.greyTextColor,
)
fontWeight: FontWeight.w500,
color: AppColors.greyTextColor,
)
],
),
CustomButton(
text: confirmButtonString.needTranslation,
onPressed: () {
///indicates that the screen has resulted success and should be closed
Navigator.pop(context,true);
text: confirmButtonString.needTranslation,
onPressed: () {
if (onSubmitted != null) {
onSubmitted!();
} else {
Navigator.pop(context, true);
}
},
)
],
@ -190,8 +166,6 @@ class MapUtilityScreen extends StatelessWidget {
);
}
textPlaceInput(context) {
return Consumer<LocationViewModel>(builder: (_, vm, __) {
return SizedBox(
@ -200,8 +174,7 @@ class MapUtilityScreen extends StatelessWidget {
labelText: "Enter Pickup Location Manually".needTranslation,
hintText: "Enter Pickup Location".needTranslation,
controller: TextEditingController(
text: vm.geocodeResponse?.results.first.formattedAddress ??
vm.selectedPrediction?.description,
text: vm.geocodeResponse?.results.first.formattedAddress ?? vm.selectedPrediction?.description,
),
leadingIcon: AppAssets.location_pickup,
isAllowLeadingIcon: true,

Loading…
Cancel
Save