Completed the HHC and CMC
parent
5e437e42a9
commit
8068de70cb
@ -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),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue