import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import '../../../domain/entities/tour.dart'; import '../../../core/constants/app_constants.dart'; import '../../blocs/tour/tour_bloc.dart'; import '../../widgets/tour_list_item.dart'; import '../../widgets/loading_indicator.dart'; import '../../widgets/error_view.dart'; import '../tour_types/stock_start_page.dart'; import '../tour_types/veh_start_page.dart'; import '../tour_types/veh_page.dart'; import '../tour_types/fsa_page.dart'; import '../tour_types/vs_page.dart'; import '../tour_types/gi_page.dart'; import '../tour_types/veh_end_page.dart'; import '../tour_types/stock_end_page.dart'; import '../scan/scan_page.dart'; class ToursPage extends StatelessWidget { const ToursPage({super.key}); @override Widget build(BuildContext context) { return Scaffold( body: BlocBuilder( builder: (context, state) { if (state is TourLoading) { return const LoadingIndicator(message: 'Touren werden geladen...'); } if (state is TourError) { return ErrorView( message: state.message, onRetry: () => context.read().add(const RefreshTours()), ); } if (state is ToursLoaded) { return _ToursListView(state: state); } return const LoadingIndicator(); }, ), ); } } class _ToursListView extends StatelessWidget { final ToursLoaded state; const _ToursListView({required this.state}); @override Widget build(BuildContext context) { final theme = Theme.of(context); return CustomScrollView( slivers: [ // Header mit Fortschritt SliverToBoxAdapter( child: _buildHeader(context), ), // Offene Touren SliverToBoxAdapter( child: Padding( padding: const EdgeInsets.fromLTRB(16, 16, 16, 8), child: Row( children: [ Icon( Icons.location_on, color: theme.colorScheme.primary, size: 20, ), const SizedBox(width: 8), Text( 'Offene Stationen', style: theme.textTheme.titleMedium?.copyWith( fontWeight: FontWeight.w600, ), ), const Spacer(), Container( padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 4), decoration: BoxDecoration( color: theme.colorScheme.primary.withValues(alpha: 26), borderRadius: BorderRadius.circular(12), ), child: Text( '${state.tours.length}', style: theme.textTheme.labelMedium?.copyWith( color: theme.colorScheme.primary, fontWeight: FontWeight.w600, ), ), ), ], ), ), ), SliverList( delegate: SliverChildBuilderDelegate( (context, index) { final tour = state.tours[index]; return TourListItem( tour: tour, onTap: () => _onTourSelected(context, tour), ); }, childCount: state.tours.length, ), ), // Erledigte Touren (falls aktiviert) if (state.showCompleted && state.completedTours.isNotEmpty) ...[ SliverToBoxAdapter( child: Padding( padding: const EdgeInsets.fromLTRB(16, 24, 16, 8), child: Row( children: [ const Icon( Icons.check_circle, color: Colors.green, size: 20, ), const SizedBox(width: 8), Text( 'Erledigte Stationen', style: theme.textTheme.titleMedium?.copyWith( fontWeight: FontWeight.w600, ), ), const Spacer(), Container( padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 4), decoration: BoxDecoration( color: Colors.green.withValues(alpha: 26), borderRadius: BorderRadius.circular(12), ), child: Text( '${state.completedTours.length}', style: theme.textTheme.labelMedium?.copyWith( color: Colors.green, fontWeight: FontWeight.w600, ), ), ), ], ), ), ), SliverList( delegate: SliverChildBuilderDelegate( (context, index) { final tour = state.completedTours[index]; return TourListItem( tour: tour, onTap: () => _onTourSelected(context, tour), isCompleted: true, ); }, childCount: state.completedTours.length, ), ), ], const SliverPadding(padding: EdgeInsets.only(bottom: 100)), ], ); } Widget _buildHeader(BuildContext context) { final theme = Theme.of(context); final completionPercentage = state.completionPercentage; return Container( margin: const EdgeInsets.all(16), padding: const EdgeInsets.all(20), decoration: BoxDecoration( gradient: LinearGradient( colors: [ theme.colorScheme.primary, theme.colorScheme.primary.withValues(alpha: 204), ], begin: Alignment.topLeft, end: Alignment.bottomRight, ), borderRadius: BorderRadius.circular(20), boxShadow: [ BoxShadow( color: theme.colorScheme.primary.withValues(alpha: 77), blurRadius: 20, offset: const Offset(0, 8), ), ], ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Container( padding: const EdgeInsets.all(12), decoration: BoxDecoration( color: Colors.white.withValues(alpha: 51), borderRadius: BorderRadius.circular(12), ), child: const Icon( Icons.route, color: Colors.white, size: 24, ), ), const SizedBox(width: 16), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( 'Tagesübersicht', style: theme.textTheme.titleSmall?.copyWith( color: Colors.white.withValues(alpha: 204), ), ), const SizedBox(height: 4), Text( '${state.completedCount} / ${state.totalCount} Stationen', style: theme.textTheme.titleLarge?.copyWith( color: Colors.white, fontWeight: FontWeight.bold, ), ), ], ), ), ], ), const SizedBox(height: 20), ClipRRect( borderRadius: BorderRadius.circular(8), child: LinearProgressIndicator( value: completionPercentage / 100, backgroundColor: Colors.white.withValues(alpha: 51), valueColor: const AlwaysStoppedAnimation(Colors.white), minHeight: 8, ), ), const SizedBox(height: 12), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( '${completionPercentage.toStringAsFixed(0)}% abgeschlossen', style: theme.textTheme.bodySmall?.copyWith( color: Colors.white.withValues(alpha: 230), ), ), if (state.isSyncing) Row( children: [ SizedBox( width: 12, height: 12, child: CircularProgressIndicator( strokeWidth: 2, valueColor: AlwaysStoppedAnimation( Colors.white.withValues(alpha: 204), ), ), ), const SizedBox(width: 6), Text( 'Sync...', style: theme.textTheme.bodySmall?.copyWith( color: Colors.white.withValues(alpha: 230), ), ), ], ), ], ), ], ), ); } void _onTourSelected(BuildContext context, Tour tour) { context.read().add(SelectTour(tour)); // Navigation zur tour-spezifischen Page final page = _getPageForTourType(tour); Navigator.push( context, MaterialPageRoute(builder: (_) => page), ); } Widget _getPageForTourType(Tour tour) { switch (tour.type) { case TourTypes.stockStart: return StockStartPage(tour: tour); case TourTypes.vehStart: return VehStartPage(tour: tour); case TourTypes.veh: return VehPage(tour: tour); case TourTypes.fsa: return FsaPage(tour: tour); case TourTypes.vs: return VsPage(tour: tour); case TourTypes.gi: return GiPage(tour: tour); case TourTypes.vehEnd: return VehEndPage(tour: tour); case TourTypes.stockEnd: return StockEndPage(tour: tour); case TourTypes.stock: // Stock (HADAG) uses similar UI to stock_start return StockStartPage(tour: tour); default: // Fallback to generic scan page for unknown types return ScanPage(tour: tour); } } }