import 'package:flutter/material.dart'; import '../models/models.dart'; import '../storage/local_storage.dart'; import '../theme.dart'; import 'about_screen.dart'; class CompareRunsScreen extends StatefulWidget { final SavedRun initialRun; const CompareRunsScreen({super.key, required this.initialRun}); @override State createState() => _CompareRunsScreenState(); } class _CompareRunsScreenState extends State { List _allRuns = []; SavedRun? _selectedRun; bool _loading = true; @override void initState() { super.initState(); _loadRuns(); } Future _loadRuns() async { final runs = await LocalStorage.getSavedRuns(); // Exclude the initial run from selection options final otherRuns = runs.where((r) => r.id != widget.initialRun.id).toList(); setState(() { _allRuns = otherRuns; _loading = false; }); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('Compare Runs'), leading: IconButton( icon: const Icon(Icons.arrow_back), onPressed: () => Navigator.pop(context), ), actions: [ IconButton( icon: const Icon(Icons.info_outline), onPressed: () => Navigator.push( context, MaterialPageRoute(builder: (_) => const AboutScreen()), ), ), ], ), body: _loading ? const Center(child: CircularProgressIndicator()) : _buildContent(), ); } Widget _buildContent() { if (_selectedRun == null) { return _buildRunSelector(); } return _buildComparison(); } Widget _buildRunSelector() { return Padding( padding: const EdgeInsets.all(24), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( 'Select a run to compare with', style: Theme.of(context).textTheme.headlineSmall, ), const SizedBox(height: 8), Text( 'Comparing: ${widget.initialRun.label}', style: Theme.of(context).textTheme.bodyMedium?.copyWith( color: AppColors.primary, ), ), const SizedBox(height: 24), Expanded( child: ListView.builder( itemCount: _allRuns.length, itemBuilder: (context, index) { final run = _allRuns[index]; return Card( margin: const EdgeInsets.only(bottom: 12), child: ListTile( title: Text(run.label), subtitle: Text(run.displayDate), trailing: const Icon(Icons.chevron_right), onTap: () => setState(() => _selectedRun = run), ), ); }, ), ), ], ), ); } Widget _buildComparison() { final runA = widget.initialRun; final runB = _selectedRun!; return SingleChildScrollView( padding: const EdgeInsets.all(24), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // Header with run labels Row( children: [ Expanded( child: _buildRunHeader(runA, 'Run A'), ), const SizedBox(width: 16), Expanded( child: _buildRunHeader(runB, 'Run B'), ), ], ), const SizedBox(height: 24), // Dominant factors comparison Text( 'Dominant Challenge', style: Theme.of(context).textTheme.titleMedium, ), const SizedBox(height: 12), _buildDominantComparison(runA, runB), const SizedBox(height: 24), // Profile changes Text( 'Profile Changes', style: Theme.of(context).textTheme.titleMedium, ), const SizedBox(height: 12), _buildProfileComparison(runA.profile, runB.profile), const SizedBox(height: 32), // Change comparison button Center( child: TextButton( onPressed: () => setState(() => _selectedRun = null), child: const Text('Compare with different run'), ), ), ], ), ); } Widget _buildRunHeader(SavedRun run, String tag) { return Container( padding: const EdgeInsets.all(12), decoration: BoxDecoration( color: AppColors.surfaceVariant, borderRadius: BorderRadius.circular(12), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( tag, style: Theme.of(context).textTheme.bodySmall?.copyWith( color: AppColors.textSecondary, ), ), const SizedBox(height: 4), Text( run.label, style: Theme.of(context).textTheme.titleSmall, maxLines: 1, overflow: TextOverflow.ellipsis, ), Text( run.displayDate, style: Theme.of(context).textTheme.bodySmall?.copyWith( color: AppColors.textSecondary, ), ), ], ), ); } Widget _buildDominantComparison(SavedRun runA, SavedRun runB) { final dominantA = runA.result.dominantFactor; final dominantB = runB.result.dominantFactor; return Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ Expanded( child: _buildCompactFactorCard(dominantA), ), const SizedBox(width: 16), Expanded( child: _buildCompactFactorCard(dominantB), ), ], ); } Widget _buildCompactFactorCard(RankedFactor? factor) { if (factor == null) { return Container( padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: AppColors.success.withAlpha(26), borderRadius: BorderRadius.circular(12), ), child: Column( children: [ const Icon(Icons.check_circle, color: AppColors.success), const SizedBox(height: 8), Text( 'Optimal', style: Theme.of(context).textTheme.titleSmall?.copyWith( color: AppColors.success, ), ), ], ), ); } return Container( padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: AppColors.primary.withAlpha(26), borderRadius: BorderRadius.circular(12), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( factor.displayName, style: Theme.of(context).textTheme.titleSmall, ), const SizedBox(height: 4), Text( '${factor.delta.rangeDisplay} mo', style: Theme.of(context).textTheme.headlineSmall?.copyWith( color: AppColors.primary, ), ), ], ), ); } Widget _buildProfileComparison(UserProfile profileA, UserProfile profileB) { final changes = []; if (profileA.age != profileB.age) { changes.add(_buildChangeRow( 'Age', '${profileA.age}', '${profileB.age}', )); } if (profileA.weightKg != profileB.weightKg) { changes.add(_buildChangeRow( 'Weight', '${profileA.weightKg.round()} kg', '${profileB.weightKg.round()} kg', )); } if (profileA.country != profileB.country) { changes.add(_buildChangeRow( 'Country', profileA.country, profileB.country, )); } if (changes.isEmpty) { return Container( padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: AppColors.surfaceVariant, borderRadius: BorderRadius.circular(12), ), child: Center( child: Text( 'No profile changes between runs', style: Theme.of(context).textTheme.bodyMedium?.copyWith( color: AppColors.textSecondary, ), ), ), ); } return Column(children: changes); } Widget _buildChangeRow(String label, String valueA, String valueB) { return Container( margin: const EdgeInsets.only(bottom: 8), padding: const EdgeInsets.all(12), decoration: BoxDecoration( color: AppColors.surfaceVariant, borderRadius: BorderRadius.circular(12), ), child: Row( children: [ Expanded( flex: 2, child: Text( label, style: Theme.of(context).textTheme.bodyMedium, ), ), Expanded( flex: 2, child: Text( valueA, style: Theme.of(context).textTheme.bodyMedium, textAlign: TextAlign.center, ), ), const Icon(Icons.arrow_forward, size: 16, color: AppColors.textSecondary), Expanded( flex: 2, child: Text( valueB, style: Theme.of(context).textTheme.bodyMedium?.copyWith( fontWeight: FontWeight.w600, ), textAlign: TextAlign.center, ), ), ], ), ); } }