1import 'package:flutter/material.dart';
2import 'package:flutter_screenutil/flutter_screenutil.dart';
3import 'package:google_maps_flutter/google_maps_flutter.dart';
4import 'package:go_router/go_router.dart';
5import 'package:geolocator/geolocator.dart';
9import '../../../../../../core/common/entities/collection_entity.dart';
10import '../../../../../../core/router/routes.dart';
11import '../../../../../../core/ui/theme/color_palette.dart';
12import '../widgets/map_button.dart';
13import '../widgets/map_details_card.dart';
20 required this.collections,
24 State<CollectionsMapView>
createState() => _CollectionsMapViewState();
27class _CollectionsMapViewState
extends State<CollectionsMapView>
28 with SingleTickerProviderStateMixin {
38 "elementType":
"labels.icon",
46 "featureType":
"transit",
61 duration:
const Duration(milliseconds: 300),
68 super.didUpdateWidget(oldWidget);
69 if (widget.collections != oldWidget.collections) {
75 final markers = <MarkerId, Marker>{};
77 for (
int i = 0; i < widget.collections.length; i++) {
82 final markerId = MarkerId(
collection.id.toString());
84 final marker = Marker(
88 infoWindow: InfoWindow(
93 Routes.collectionDetailsScreen.route,
106 markers[markerId] = marker;
116 final pictureRecorder = ui.PictureRecorder();
117 final canvas = Canvas(pictureRecorder);
119 final textPainter = TextPainter(
120 textDirection: TextDirection.ltr,
121 textAlign: TextAlign.center,
124 canvas.drawCircle(Offset(size / 2, size / 2), size / 2,
paint);
126 final borderPaint = Paint()
127 ..
color = Colors.white
128 ..style = PaintingStyle.stroke
130 canvas.drawCircle(Offset(size / 2, size / 2), size / 2 - 4, borderPaint);
132 textPainter.text = TextSpan(
133 text: number.toString(),
134 style:
const TextStyle(
136 fontWeight: FontWeight.bold,
141 textPainter.layout();
145 (size - textPainter.width) / 2,
146 (size - textPainter.height) / 2,
150 final img = await pictureRecorder.endRecording().toImage(
154 final data = await img.toByteData(format: ui.ImageByteFormat.png);
156 return BitmapDescriptor.bytes(data!.buffer.asUint8List(), height: 35.sp);
160 Widget
build(BuildContext context) {
161 LatLng initialPosition =
const LatLng(51.5074, -0.1278);
163 for (
final collection in widget.collections) {
165 initialPosition = LatLng(
175 initialCameraPosition: CameraPosition(
176 target: initialPosition,
179 markers: Set<Marker>.of(
_markers.values),
180 onMapCreated: (GoogleMapController controller) {
181 _mapController = controller;
187 myLocationEnabled:
true,
188 myLocationButtonEnabled:
false,
189 zoomControlsEnabled:
false,
190 mapToolbarEnabled:
false,
191 compassEnabled:
true,
202 color: Colors.white.withValues(alpha: 0.7),
204 child: CircularProgressIndicator(),
211 mainAxisSize: MainAxisSize.min,
214 icon: Icons.my_location,
223 _mapController?.animateCamera(CameraUpdate.zoomIn());
231 _mapController?.animateCamera(CameraUpdate.zoomOut());
243 child: AnimatedBuilder(
245 builder: (context,
child) {
250 return Transform.translate(
258 child: MapDetailsCard(
272 bool serviceEnabled = await Geolocator.isLocationServiceEnabled();
273 if (!serviceEnabled) {
275 ScaffoldMessenger.of(context).showSnackBar(
278 'Location services are disabled. Please enable them in settings.'),
279 duration: Duration(seconds: 3),
286 LocationPermission permission = await Geolocator.checkPermission();
287 if (permission == LocationPermission.denied) {
288 permission = await Geolocator.requestPermission();
289 if (permission == LocationPermission.denied) {
291 ScaffoldMessenger.of(context).showSnackBar(
293 content:
Text(
'Location permission denied'),
294 duration: Duration(seconds: 2),
302 if (permission == LocationPermission.deniedForever) {
304 ScaffoldMessenger.of(context).showSnackBar(
307 'Location permissions are permanently denied. Please enable them in app settings.'),
308 duration: Duration(seconds: 3),
315 final position = await Geolocator.getCurrentPosition(
316 locationSettings:
const LocationSettings(
317 accuracy: LocationAccuracy.high,
318 timeLimit: Duration(seconds: 10),
323 CameraUpdate.newCameraPosition(
325 target: LatLng(position.latitude, position.longitude),
332 ScaffoldMessenger.of(context).showSnackBar(
334 content:
Text(
'Unable to get your location: ${e.toString()}'),
335 duration:
const Duration(seconds: 3),
override void initState()
class App extends StatefulWidget build(BuildContext context)
override void didUpdateWidget(CollectionsMapView oldWidget)
late AnimationController _animationController
void _goToUserLocation() async
Future< void > _createMarkers() async
Future< BitmapDescriptor > _getMarkerBitmap(int number) async
class EndLocationChooserScreen extends StatefulWidget _mapController
class SearchWeeklyCollectionsEvent extends WeeklyCollectionsEvent collection
style Text( '${ 'scheduling.reference'.tr()}:${collection.internalCode}', style:Theme.of(context).textTheme.bodySmall,)
style SizedBox(height:2.h)
style Column(crossAxisAlignment:CrossAxisAlignment.end, children:[Container(padding:EdgeInsets.symmetric(horizontal:8.w, vertical:4.h), decoration:BoxDecoration(color:ColorPalette.tiffanyBlue.withValues(alpha:0.1), borderRadius:BorderRadius.circular(12),), child:Text(collection.type ?? '', style:Theme.of(context).textTheme.bodySmall?.copyWith(color:ColorPalette.tiffanyBlue, fontWeight:FontWeight.bold,),),),],)