import 'package:flutter/material.dart'; import 'package:mileograph_flutter/services/data_service.dart'; import 'package:mileograph_flutter/services/distance_unit_service.dart'; import 'package:provider/provider.dart'; enum _LeaderboardScope { global, friends } class LeaderboardPanel extends StatefulWidget { const LeaderboardPanel({super.key}); @override State createState() => _LeaderboardPanelState(); } class _LeaderboardPanelState extends State { _LeaderboardScope _scope = _LeaderboardScope.global; @override Widget build(BuildContext context) { final data = context.watch(); final distanceUnits = context.watch(); final leaderboard = _scope == _LeaderboardScope.global ? (data.homepageStats?.leaderboard ?? []) : data.friendsLeaderboard; final loading = _scope == _LeaderboardScope.global ? data.isHomepageLoading : data.isFriendsLeaderboardLoading; final textTheme = Theme.of(context).textTheme; if (loading && leaderboard.isEmpty) { return const Padding( padding: EdgeInsets.all(16.0), child: Center(child: CircularProgressIndicator()), ); } return Card( clipBehavior: Clip.antiAlias, child: Padding( padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ Row( children: [ const Icon(Icons.emoji_events, size: 20), const SizedBox(width: 8), Expanded( child: Text( "Leaderboard", style: textTheme.titleMedium?.copyWith( fontWeight: FontWeight.w800, ), ), ), if (leaderboard.isNotEmpty && MediaQuery.of(context).size.width > 600) Container( padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), decoration: BoxDecoration( color: Theme.of(context).colorScheme.surfaceContainerHighest, borderRadius: BorderRadius.circular(10), ), child: Text( 'Top ${leaderboard.length}', style: textTheme.labelSmall, ), ), ], ), const SizedBox(height: 8), Center( child: SegmentedButton<_LeaderboardScope>( segments: const [ ButtonSegment( value: _LeaderboardScope.global, label: Text('Global'), ), ButtonSegment( value: _LeaderboardScope.friends, label: Text('Friends'), ), ], selected: {_scope}, onSelectionChanged: (vals) async { if (vals.isEmpty) return; final selected = vals.first; setState(() => _scope = selected); if (selected == _LeaderboardScope.friends && data.friendsLeaderboard.isEmpty && !data.isFriendsLeaderboardLoading) { await data.fetchFriendsLeaderboard(); } else if (selected == _LeaderboardScope.global && (data.homepageStats?.leaderboard.isEmpty ?? true) && !data.isHomepageLoading) { await data.fetchHomepageStats(); } }, style: SegmentedButton.styleFrom( visualDensity: VisualDensity.compact, padding: const EdgeInsets.symmetric(horizontal: 8), ), ), ), const SizedBox(height: 8), if (leaderboard.isEmpty) const Padding( padding: EdgeInsets.all(8.0), child: Text('No leaderboard data yet'), ) else Column( children: [ for (int index = 0; index < leaderboard.length; index++) ...[ ListTile( contentPadding: EdgeInsets.zero, dense: true, leading: CircleAvatar( radius: 18, backgroundColor: Theme.of(context).colorScheme.secondaryContainer, child: Text( '${index + 1}', style: textTheme.labelLarge?.copyWith( fontWeight: FontWeight.w800, ), ), ), title: Text( leaderboard[index].userFullName, style: textTheme.titleSmall?.copyWith( fontWeight: FontWeight.w700, ), ), trailing: Text( distanceUnits.format( leaderboard[index].mileage, decimals: 1, ), style: textTheme.labelLarge?.copyWith( fontWeight: FontWeight.w700, ), ), ), if (index != leaderboard.length - 1) const Divider(height: 12), ], ], ), ], ), ), ); } }