feat: Implement Google Maps integration for shift details and enhance UI components

This commit is contained in:
Achintha Isuru
2026-03-19 15:11:15 -04:00
parent 8121a718bb
commit 2a99587d2f
9 changed files with 141 additions and 7 deletions

View File

@@ -45,6 +45,11 @@ public final class GeneratedPluginRegistrant {
} catch (Exception e) {
Log.e(TAG, "Error registering plugin geolocator_android, com.baseflow.geolocator.GeolocatorPlugin", e);
}
try {
flutterEngine.getPlugins().add(new io.flutter.plugins.googlemaps.GoogleMapsPlugin());
} catch (Exception e) {
Log.e(TAG, "Error registering plugin google_maps_flutter_android, io.flutter.plugins.googlemaps.GoogleMapsPlugin", e);
}
try {
flutterEngine.getPlugins().add(new io.flutter.plugins.imagepicker.ImagePickerPlugin());
} catch (Exception e) {

View File

@@ -36,6 +36,12 @@
@import geolocator_apple;
#endif
#if __has_include(<google_maps_flutter_ios/FGMGoogleMapsPlugin.h>)
#import <google_maps_flutter_ios/FGMGoogleMapsPlugin.h>
#else
@import google_maps_flutter_ios;
#endif
#if __has_include(<image_picker_ios/FLTImagePickerPlugin.h>)
#import <image_picker_ios/FLTImagePickerPlugin.h>
#else
@@ -80,6 +86,7 @@
[FLTFirebaseCorePlugin registerWithRegistrar:[registry registrarForPlugin:@"FLTFirebaseCorePlugin"]];
[FlutterLocalNotificationsPlugin registerWithRegistrar:[registry registrarForPlugin:@"FlutterLocalNotificationsPlugin"]];
[GeolocatorPlugin registerWithRegistrar:[registry registrarForPlugin:@"GeolocatorPlugin"]];
[FGMGoogleMapsPlugin registerWithRegistrar:[registry registrarForPlugin:@"FGMGoogleMapsPlugin"]];
[FLTImagePickerPlugin registerWithRegistrar:[registry registrarForPlugin:@"FLTImagePickerPlugin"]];
[FPPPackageInfoPlusPlugin registerWithRegistrar:[registry registrarForPlugin:@"FPPPackageInfoPlusPlugin"]];
[RecordIosPlugin registerWithRegistrar:[registry registrarForPlugin:@"RecordIosPlugin"]];

View File

@@ -140,6 +140,8 @@ class _ShiftDetailsPageState extends State<ShiftDetailsPage> {
ShiftLocationSection(
location: detail.location,
address: detail.address ?? '',
latitude: detail.latitude,
longitude: detail.longitude,
locationLabel: context.t.staff_shifts.shift_details.location,
tbdLabel: context.t.staff_shifts.shift_details.tbd,
getDirectionLabel: context.t.staff_shifts.shift_details.get_direction,

View File

@@ -57,7 +57,7 @@ class ShiftDateTimeSection extends StatelessWidget {
const Icon(
UiIcons.calendar,
size: 20,
color: UiColors.primary,
color: UiColors.textPrimary,
),
const SizedBox(width: UiConstants.space2),
Text(

View File

@@ -32,7 +32,7 @@ class ShiftDescriptionSection extends StatelessWidget {
const SizedBox(height: UiConstants.space2),
Text(
description,
style: UiTypography.body2r.textSecondary,
style: UiTypography.body2r,
),
],
),

View File

@@ -45,8 +45,8 @@ class ShiftDetailsHeader extends StatelessWidget {
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(detail.title, style: UiTypography.headline1b.textPrimary),
Text(detail.roleName, style: UiTypography.body1m.textSecondary),
Text(detail.roleName, style: UiTypography.headline1b.textPrimary),
Text(detail.clientName, style: UiTypography.body1m.textSecondary),
],
),
),

View File

@@ -1,6 +1,7 @@
import 'package:core_localization/core_localization.dart';
import 'package:design_system/design_system.dart';
import 'package:flutter/material.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:url_launcher/url_launcher.dart';
/// A section displaying the shift's location, address, and "Get direction" action.
@@ -10,6 +11,8 @@ class ShiftLocationSection extends StatelessWidget {
super.key,
required this.location,
required this.address,
this.latitude,
this.longitude,
required this.locationLabel,
required this.tbdLabel,
required this.getDirectionLabel,
@@ -21,6 +24,12 @@ class ShiftLocationSection extends StatelessWidget {
/// Street address.
final String address;
/// Latitude coordinate for map preview.
final double? latitude;
/// Longitude coordinate for map preview.
final double? longitude;
/// Localization string for location section title.
final String locationLabel;
@@ -97,15 +106,53 @@ class ShiftLocationSection extends StatelessWidget {
),
],
),
if (latitude != null && longitude != null) ...<Widget>[
ClipRRect(
borderRadius: BorderRadius.circular(UiConstants.radiusBase),
child: SizedBox(
height: 180,
width: double.infinity,
child: GoogleMap(
initialCameraPosition: CameraPosition(
target: LatLng(latitude!, longitude!),
zoom: 15,
),
markers: <Marker>{
Marker(
markerId: const MarkerId('shift_location'),
position: LatLng(latitude!, longitude!),
),
},
liteModeEnabled: true,
myLocationButtonEnabled: false,
myLocationEnabled: false,
zoomControlsEnabled: false,
mapToolbarEnabled: false,
compassEnabled: false,
rotateGesturesEnabled: false,
scrollGesturesEnabled: false,
tiltGesturesEnabled: false,
zoomGesturesEnabled: false,
),
),
),
const SizedBox(height: UiConstants.space3),
],
],
),
);
}
Future<void> _openDirections(BuildContext context) async {
final String destination = Uri.encodeComponent(
String destination;
if (latitude != null && longitude != null) {
destination = '$latitude,$longitude';
} else {
destination = Uri.encodeComponent(
address.isNotEmpty ? address : location,
);
}
final String url =
'https://www.google.com/maps/dir/?api=1&destination=$destination';

View File

@@ -29,6 +29,7 @@ dependencies:
url_launcher: ^6.3.1
bloc: ^8.1.4
meta: ^1.17.0
google_maps_flutter: ^2.10.0
dev_dependencies:
flutter_test:

View File

@@ -257,6 +257,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "3.0.7"
csslib:
dependency: transitive
description:
name: csslib
sha256: "09bad715f418841f976c77db72d5398dc1253c21fb9c0c7f0b0b985860b2d58e"
url: "https://pub.dev"
source: hosted
version: "1.0.2"
csv:
dependency: transitive
description:
@@ -637,6 +645,54 @@ packages:
url: "https://pub.dev"
source: hosted
version: "7.0.2"
google_maps:
dependency: transitive
description:
name: google_maps
sha256: "5d410c32112d7c6eb7858d359275b2aa04778eed3e36c745aeae905fb2fa6468"
url: "https://pub.dev"
source: hosted
version: "8.2.0"
google_maps_flutter:
dependency: transitive
description:
name: google_maps_flutter
sha256: "0114a31e177f650f0972347d93122c42661a75b869561ff6a374cc42ff3af886"
url: "https://pub.dev"
source: hosted
version: "2.16.0"
google_maps_flutter_android:
dependency: transitive
description:
name: google_maps_flutter_android
sha256: "68a3907c90dc37caffbcfc1093541ef2c18d6ebb53296fdb9f04822d16269353"
url: "https://pub.dev"
source: hosted
version: "2.19.3"
google_maps_flutter_ios:
dependency: transitive
description:
name: google_maps_flutter_ios
sha256: c855600dce17e77e8af96edcf85cb68501675bb77a72f85009d08c17a8805ace
url: "https://pub.dev"
source: hosted
version: "2.18.0"
google_maps_flutter_platform_interface:
dependency: transitive
description:
name: google_maps_flutter_platform_interface
sha256: ddbe34435dfb34e83fca295c6a8dcc53c3b51487e9eec3c737ce4ae605574347
url: "https://pub.dev"
source: hosted
version: "2.15.0"
google_maps_flutter_web:
dependency: transitive
description:
name: google_maps_flutter_web
sha256: "6cefe4ef4cc61dc0dfba4c413dec4bd105cb6b9461bfbe1465ddd09f80af377d"
url: "https://pub.dev"
source: hosted
version: "0.6.2"
google_places_flutter:
dependency: transitive
description:
@@ -669,6 +725,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "0.20.5"
html:
dependency: transitive
description:
name: html
sha256: "6d1264f2dffa1b1101c25a91dff0dc2daee4c18e87cd8538729773c073dbf602"
url: "https://pub.dev"
source: hosted
version: "0.15.6"
http:
dependency: transitive
description:
@@ -1189,6 +1253,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "0.28.0"
sanitize_html:
dependency: transitive
description:
name: sanitize_html
sha256: "12669c4a913688a26555323fb9cec373d8f9fbe091f2d01c40c723b33caa8989"
url: "https://pub.dev"
source: hosted
version: "2.1.0"
shared_preferences:
dependency: transitive
description: