import 'package:flutter/material.dart'; import '../providers/delivery_provider.dart'; import '../models/delivery_history.dart'; class StatisticsPage extends StatefulWidget { final DeliveryProvider deliveryProvider; final String routeName; const StatisticsPage({ super.key, required this.deliveryProvider, required this.routeName, }); @override State createState() => _StatisticsPageState(); } class _StatisticsPageState extends State { List _stats = []; int _totalDeliveries = 0; int _weeklyDeliveries = 0; bool _loading = true; @override void initState() { super.initState(); _loadStats(); } Future _loadStats() async { final stats = await widget.deliveryProvider.getStats(days: 30); final total = await widget.deliveryProvider.totalDeliveries; final weekly = await widget.deliveryProvider.weeklyDeliveries; if (mounted) { setState(() { _stats = stats; _totalDeliveries = total; _weeklyDeliveries = weekly; _loading = false; }); } } @override Widget build(BuildContext context) { final provider = widget.deliveryProvider; final todayDelivered = provider.deliveredCount; final totalStops = provider.totalStops; final newspaperCounts = provider.newspaperCounts; final totalNewspapers = provider.totalNewspapers; // Calculate averages final daysWithDeliveries = _stats.where((s) => s.deliveredCount > 0).length; final avgPerDay = daysWithDeliveries > 0 ? (_stats.fold(0, (sum, s) => sum + s.deliveredCount) / daysWithDeliveries) : 0.0; return Scaffold( appBar: AppBar( title: Text('Statistics - ${widget.routeName}'), ), body: _loading ? const Center(child: CircularProgressIndicator()) : RefreshIndicator( onRefresh: _loadStats, child: ListView( padding: const EdgeInsets.all(16), children: [ // Today's progress _buildCard( icon: Icons.today, title: 'Today', child: Column( children: [ const SizedBox(height: 8), LinearProgressIndicator( value: totalStops > 0 ? todayDelivered / totalStops : 0, minHeight: 10, borderRadius: BorderRadius.circular(5), ), const SizedBox(height: 8), Text( '$todayDelivered / $totalStops stops delivered', style: const TextStyle(fontSize: 18, fontWeight: FontWeight.bold), ), if (totalStops > 0) Text( '${(todayDelivered / totalStops * 100).toStringAsFixed(0)}% complete', style: TextStyle(color: Colors.grey[600]), ), ], ), ), const SizedBox(height: 12), // Newspaper counts _buildCard( icon: Icons.newspaper, title: 'Newspapers', child: Column( children: [ const SizedBox(height: 8), Text( '$totalNewspapers total newspapers', style: const TextStyle(fontSize: 16, fontWeight: FontWeight.w600), ), const SizedBox(height: 12), Wrap( spacing: 12, runSpacing: 8, alignment: WrapAlignment.center, children: newspaperCounts.entries.map((e) { final color = _npColor(e.key); return Chip( avatar: CircleAvatar( backgroundColor: color, radius: 8, ), label: Text('${e.key}: ${e.value}'), ); }).toList(), ), ], ), ), const SizedBox(height: 12), // Summary stats Row( children: [ Expanded( child: _buildStatCard( icon: Icons.calendar_view_week, label: 'This Week', value: '$_weeklyDeliveries', color: Colors.blue, ), ), const SizedBox(width: 12), Expanded( child: _buildStatCard( icon: Icons.all_inclusive, label: 'Total All Time', value: '$_totalDeliveries', color: Colors.green, ), ), ], ), const SizedBox(height: 12), Row( children: [ Expanded( child: _buildStatCard( icon: Icons.analytics, label: 'Avg/Day', value: avgPerDay.toStringAsFixed(1), color: Colors.orange, ), ), const SizedBox(width: 12), Expanded( child: _buildStatCard( icon: Icons.date_range, label: 'Active Days', value: '$daysWithDeliveries', color: Colors.purple, ), ), ], ), const SizedBox(height: 20), // Daily history _buildCard( icon: Icons.history, title: 'Delivery History (Last 30 Days)', child: _stats.isEmpty ? const Padding( padding: EdgeInsets.all(16), child: Text( 'No deliveries recorded yet', textAlign: TextAlign.center, style: TextStyle(color: Colors.grey), ), ) : Column( children: _stats.map((stat) { final date = DateTime.tryParse(stat.date); final dateStr = date != null ? '${date.day}/${date.month}/${date.year}' : stat.date; final pct = stat.totalCount > 0 ? (stat.deliveredCount / stat.totalCount * 100) .toStringAsFixed(0) : '0'; return ListTile( dense: true, leading: CircleAvatar( radius: 16, backgroundColor: stat.deliveredCount == stat.totalCount ? Colors.green : Colors.orange, child: Text( '$pct%', style: const TextStyle( color: Colors.white, fontSize: 10, fontWeight: FontWeight.bold, ), ), ), title: Text(dateStr), subtitle: Text( '${stat.deliveredCount} / ${stat.totalCount} stops', ), trailing: stat.deliveredCount == stat.totalCount ? const Icon(Icons.check_circle, color: Colors.green) : null, ); }).toList(), ), ), ], ), ), ); } Widget _buildCard({ required IconData icon, required String title, required Widget child, }) { return Card( child: Padding( padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Icon(icon, size: 20), const SizedBox(width: 8), Text(title, style: const TextStyle(fontSize: 16, fontWeight: FontWeight.bold)), ], ), child, ], ), ), ); } Widget _buildStatCard({ required IconData icon, required String label, required String value, required Color color, }) { return Card( child: Padding( padding: const EdgeInsets.all(16), child: Column( children: [ Icon(icon, color: color, size: 28), const SizedBox(height: 8), Text( value, style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold, color: color), ), const SizedBox(height: 4), Text(label, style: TextStyle(color: Colors.grey[600], fontSize: 12)), ], ), ), ); } Color _npColor(String np) { switch (np) { case 'BN': return Colors.red; case 'AD': return Colors.blue; case 'TEL': return Colors.orange; case 'VK': return Colors.purple; default: return Colors.grey; } } }