import 'package:flutter/material.dart'; import '../models/schedule.dart' as schedule; import '../screens/navigation_screen.dart'; import '../services/schedule_service.dart'; /// Route card widget showing route details class RouteCard extends StatelessWidget { final schedule.Route route; final VoidCallback onTap; const RouteCard({ super.key, required this.route, required this.onTap, }); Color _getStatusColor(String status) { switch (status) { case 'scheduled': return Colors.blue; case 'in_progress': return Colors.orange; case 'completed': return Colors.green; case 'cancelled': return Colors.red; default: return Colors.grey; } } String _getStatusLabel(String status) { switch (status) { case 'scheduled': return 'Planned'; case 'in_progress': return 'In Progress'; case 'completed': return 'Completed'; case 'cancelled': return 'Cancelled'; default: return status; } } String _formatTime(DateTime time) { return '${time.hour.toString().padLeft(2, '0')}:${time.minute.toString().padLeft(2, '0')}'; } @override Widget build(BuildContext context) { final colorScheme = Theme.of(context).colorScheme; final statusColor = _getStatusColor(route.status); final startTimeStr = _formatTime(route.startTime); return Material( color: Colors.transparent, child: InkWell( onTap: () async { try { final scheduleService = ScheduleService(); await scheduleService.updateRouteStatus(route.id, 'in_progress'); } catch (_) { // Ignore status update errors here; navigation should still open. } Navigator.of(context).push( MaterialPageRoute( builder: (context) => NavigationScreen(route: route), ), ); }, borderRadius: BorderRadius.circular(20), splashFactory: InkSparkle.splashFactory, child: Card( margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), elevation: 0, color: colorScheme.surface, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)), child: Padding( padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // Header: Line number + Status Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ // Line number - Large and prominent Container( padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8), decoration: BoxDecoration( gradient: LinearGradient( colors: [colorScheme.primary, colorScheme.tertiary], begin: Alignment.topLeft, end: Alignment.bottomRight, ), borderRadius: BorderRadius.circular(8), ), child: Text( 'Line ${route.busLine.lineNumber}', style: Theme.of(context).textTheme.titleMedium?.copyWith( color: Colors.white, fontWeight: FontWeight.bold, fontSize: 18, ), ), ), // Status badge Container( padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 6), decoration: BoxDecoration( color: statusColor.withOpacity(0.14), border: Border.all(color: statusColor), borderRadius: BorderRadius.circular(20), ), child: Text( _getStatusLabel(route.status), style: TextStyle( color: statusColor, fontWeight: FontWeight.w600, fontSize: 12, ), ), ), ], ), const SizedBox(height: 16), // Route info: Start -> End Row( children: [ Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( 'From', style: Theme.of(context).textTheme.labelSmall, ), Text( route.busLine.startStop, style: Theme.of(context).textTheme.titleSmall?.copyWith( fontWeight: FontWeight.w600, ), ), ], ), ), Icon( Icons.arrow_forward, color: colorScheme.outline, ), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.end, children: [ Text( 'To', style: Theme.of(context).textTheme.labelSmall, ), Text( route.busLine.endStop, style: Theme.of(context).textTheme.titleSmall?.copyWith( fontWeight: FontWeight.w600, ), ), ], ), ), ], ), const SizedBox(height: 16), // Bus info and time Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ // Bus type Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( 'Bus', style: Theme.of(context).textTheme.labelSmall, ), Text( '${route.busType.name} (${route.busType.seatCapacity} seats)', style: Theme.of(context).textTheme.titleSmall?.copyWith( fontWeight: FontWeight.w600, ), ), const SizedBox(height: 4), Text( route.busType.licensePlate, style: Theme.of(context).textTheme.labelMedium?.copyWith( color: colorScheme.onSurfaceVariant, ), ), ], ), // Start time Column( crossAxisAlignment: CrossAxisAlignment.end, children: [ Text( 'Start Time', style: Theme.of(context).textTheme.labelSmall, ), Text( startTimeStr, style: Theme.of(context).textTheme.headlineSmall?.copyWith( fontWeight: FontWeight.bold, color: colorScheme.primary, ), ), const SizedBox(height: 4), Text( '${route.busLine.estimatedDuration} min duration', style: Theme.of(context).textTheme.labelMedium?.copyWith( color: colorScheme.onSurfaceVariant, ), ), ], ), ], ), ], ), ), ), ), ); } }