import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:intl/intl.dart'; import '../../../../core/theme/app_theme.dart'; import '../../../../core/widgets/status_badge.dart'; import '../../../../services/location/location_service.dart'; import '../../../../services/maps/navigation_service.dart'; import '../../data/models/route_model.dart'; import '../../data/models/stop_model.dart'; import '../providers/route_provider.dart'; import '../widgets/stop_card.dart'; import 'map_view_page.dart'; class RouteDetailsPage extends StatelessWidget { const RouteDetailsPage({super.key}); @override Widget build(BuildContext context) { return Consumer( builder: (context, routeProvider, child) { final route = routeProvider.currentRoute; if (route == null) { return Scaffold( appBar: AppBar( title: const Text('Route Details'), ), body: const Center( child: Text('No route selected'), ), ); } return Scaffold( appBar: AppBar( title: Text('Route ${route.id}'), actions: [ IconButton( icon: const Icon(Icons.map), onPressed: () { Navigator.push( context, MaterialPageRoute( builder: (context) => MapViewPage(route: route), ), ); }, ), ], ), body: Column( children: [ _buildRouteHeader(context, route), const Divider(height: 1), Expanded( child: ListView.builder( padding: const EdgeInsets.symmetric(vertical: 8), itemCount: route.stops.length, itemBuilder: (context, index) { final stop = route.stops[index]; return StopCard( stop: stop, onTap: () { _showStopDetails(context, route, stop); }, onNavigate: () { _navigateToStop(context, stop); }, ); }, ), ), ], ), floatingActionButton: _buildActionButton(context, route), ); }, ); } Widget _buildRouteHeader(BuildContext context, RouteModel route) { return Container( padding: const EdgeInsets.all(16), color: Colors.white, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( DateFormat('EEEE, MMM dd').format(route.date), style: Theme.of(context).textTheme.titleMedium, ), StatusBadge( status: route.status.toString().split('.').last, fontSize: 14, ), ], ), const SizedBox(height: 16), Row( mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ _buildInfoItem( context, Icons.route, '${route.totalDistance.toStringAsFixed(1)} km', 'Distance', ), _buildInfoItem( context, Icons.access_time, '${route.estimatedDuration} min', 'Duration', ), _buildInfoItem( context, Icons.location_on, '${route.stops.length}', 'Stops', ), ], ), const SizedBox(height: 16), ClipRRect( borderRadius: BorderRadius.circular(8), child: LinearProgressIndicator( value: route.progressPercentage / 100, minHeight: 12, backgroundColor: Colors.grey[300], valueColor: AlwaysStoppedAnimation( route.status == RouteStatus.completed ? AppTheme.completedColor : AppTheme.inProgressColor, ), ), ), const SizedBox(height: 8), Text( '${route.completedStopsCount}/${route.totalStopsCount} stops completed', style: Theme.of(context).textTheme.bodySmall, textAlign: TextAlign.center, ), ], ), ); } Widget _buildInfoItem( BuildContext context, IconData icon, String value, String label, ) { return Column( children: [ Icon(icon, color: AppTheme.primaryColor, size: 24), const SizedBox(height: 8), Text( value, style: Theme.of(context).textTheme.titleMedium?.copyWith( fontWeight: FontWeight.bold, ), ), Text( label, style: Theme.of(context).textTheme.bodySmall, ), ], ); } Widget? _buildActionButton(BuildContext context, RouteModel route) { if (route.status == RouteStatus.completed || route.status == RouteStatus.cancelled) { return null; } final routeProvider = context.read(); if (route.status == RouteStatus.notStarted) { return FloatingActionButton.extended( onPressed: () async { final success = await routeProvider.startRoute(route.id); if (context.mounted) { ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text( success ? 'Route started!' : 'Failed to start route', ), backgroundColor: success ? AppTheme.successColor : AppTheme.errorColor, ), ); } }, icon: const Icon(Icons.play_arrow), label: const Text('Start Route'), ); } if (route.status == RouteStatus.inProgress) { final allCompleted = route.stops.every((stop) => stop.status == StopStatus.completed); if (allCompleted) { return FloatingActionButton.extended( onPressed: () async { final success = await routeProvider.completeRoute(route.id); if (context.mounted) { ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text( success ? 'Route completed!' : 'Failed to complete route', ), backgroundColor: success ? AppTheme.successColor : AppTheme.errorColor, ), ); } }, icon: const Icon(Icons.check), label: const Text('Complete Route'), ); } } return null; } void _showStopDetails( BuildContext context, RouteModel route, StopModel stop) { showModalBottomSheet( context: context, isScrollControlled: true, shape: const RoundedRectangleBorder( borderRadius: BorderRadius.vertical(top: Radius.circular(20)), ), builder: (context) => DraggableScrollableSheet( initialChildSize: 0.7, minChildSize: 0.5, maxChildSize: 0.9, expand: false, builder: (context, scrollController) => Padding( padding: const EdgeInsets.all(16), child: ListView( controller: scrollController, children: [ Center( child: Container( width: 40, height: 4, decoration: BoxDecoration( color: Colors.grey[300], borderRadius: BorderRadius.circular(2), ), ), ), const SizedBox(height: 16), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( 'Stop Details', style: Theme.of(context).textTheme.titleLarge, ), StatusBadge( status: stop.status.toString().split('.').last, ), ], ), const SizedBox(height: 24), _buildDetailRow( context, 'Customer', stop.customerName, Icons.person, ), _buildDetailRow( context, 'Type', stop.type == StopType.pickup ? 'Pickup' : 'Dropoff', Icons.local_shipping, ), if (stop.customerPhone != null) _buildDetailRow( context, 'Phone', stop.customerPhone!, Icons.phone, ), _buildDetailRow( context, 'Scheduled', DateFormat('hh:mm a').format(stop.scheduledTime), Icons.schedule, ), if (stop.location.address != null) _buildDetailRow( context, 'Address', stop.location.address!, Icons.location_on, ), if (stop.items.isNotEmpty) ...[ const SizedBox(height: 16), Text( 'Items', style: Theme.of(context).textTheme.titleMedium, ), const SizedBox(height: 8), ...stop.items.map((item) => Padding( padding: const EdgeInsets.symmetric(vertical: 4), child: Row( children: [ const Icon(Icons.check_circle_outline, size: 20), const SizedBox(width: 8), Text(item), ], ), )), ], const SizedBox(height: 24), if (stop.status == StopStatus.pending || stop.status == StopStatus.inProgress) ...[ Row( children: [ Expanded( child: ElevatedButton.icon( onPressed: () { Navigator.pop(context); _navigateToStop(context, stop); }, icon: const Icon(Icons.navigation), label: const Text('Navigate'), ), ), const SizedBox(width: 12), Expanded( child: ElevatedButton.icon( onPressed: () async { Navigator.pop(context); final success = await context .read() .updateStopStatus( route.id, stop.id, StopStatus.completed, ); if (context.mounted) { ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text( success ? 'Stop completed!' : 'Failed to complete stop', ), backgroundColor: success ? AppTheme.successColor : AppTheme.errorColor, ), ); } }, icon: const Icon(Icons.check), label: const Text('Complete'), ), ), ], ), ], ], ), ), ), ); } Widget _buildDetailRow( BuildContext context, String label, String value, IconData icon, ) { return Padding( padding: const EdgeInsets.symmetric(vertical: 8), child: Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ Icon(icon, size: 20, color: Colors.grey), const SizedBox(width: 12), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( label, style: Theme.of(context).textTheme.bodySmall, ), const SizedBox(height: 4), Text( value, style: Theme.of(context).textTheme.bodyLarge, ), ], ), ), ], ), ); } Future _navigateToStop(BuildContext context, StopModel stop) async { final locationService = LocationService(); final navigationService = NavigationService(); // Get current location final currentPosition = await locationService.getCurrentLocation(); final success = await navigationService.openNavigation( destinationLat: stop.location.latitude, destinationLng: stop.location.longitude, originLat: currentPosition?.latitude, originLng: currentPosition?.longitude, destinationName: stop.customerName, ); if (!success && context.mounted) { ScaffoldMessenger.of(context).showSnackBar( const SnackBar( content: Text('Failed to open navigation'), backgroundColor: AppTheme.errorColor, ), ); } } }