import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:go_router/go_router.dart'; import '../../../../core/locator/locator.dart'; import '../../../../core/theme/app_theme.dart'; import '../../../../core/widgets/game_ui.dart'; import '../../../wallet/presentation/bloc/wallet_bloc.dart'; import '../../../wallet/presentation/bloc/wallet_event.dart'; import '../../../wallet/presentation/bloc/wallet_state.dart'; import '../../../wallet/presentation/bloc/wallet_status.dart'; import '../../data/data_source/remote/tournament_api_provider.dart'; import '../../domain/entities/tournament.dart'; import '../widgets/tournament_guide.dart'; import 'tournament_standings_screen.dart'; /// فهرستِ تورنومنت‌ها: جایزه، ورودی، وضعیت و دکمه‌ی ثبت‌نام / جدول. class TournamentsScreen extends StatefulWidget { const TournamentsScreen({super.key}); @override State createState() => _TournamentsScreenState(); } class _TournamentsScreenState extends State { final _api = locator(); late Future> _future; int? _busyId; @override void initState() { super.initState(); _future = _api.getTournaments(); } void _reload() => setState(() { _future = _api.getTournaments(); }); Future _join(Tournament t) async { setState(() => _busyId = t.id); final err = await _api.join(t.id); if (!mounted) return; setState(() => _busyId = null); if (err == null) { context.read().add(LoadWalletEvent()); ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('ثبت‌نام انجام شد ✓')), ); _reload(); } else { ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(err))); } } void _openStandings(Tournament t) { Navigator.of(context).push(MaterialPageRoute( builder: (_) => TournamentStandingsScreen(tournament: t), )); } @override Widget build(BuildContext context) { return Scaffold( body: GameBackground( child: SafeArea( child: Column( children: [ Padding( padding: const EdgeInsets.all(12), child: Row(children: [ const AppBackButton(), const Spacer(), const GlowText('تورنومنت‌ها', size: 24), const Spacer(), IconButton( tooltip: 'راهنما', onPressed: () => TournamentGuide.show(context), icon: const Icon(Icons.help_outline, color: AppColors.gold), ), BlocBuilder( builder: (context, s) { final w = s.walletStatus is WalletLoaded ? (s.walletStatus as WalletLoaded).wallet : null; return StatChip( icon: Icons.monetization_on, value: '${w?.coins ?? 0}', ); }, ), ]), ), Expanded( child: RefreshIndicator( color: AppColors.gold, onRefresh: () async => _reload(), child: FutureBuilder>( future: _future, builder: (context, snap) { if (snap.connectionState != ConnectionState.done) { return const Center( child: CircularProgressIndicator(color: AppColors.gold)); } if (snap.hasError) { return _retry(); } final items = snap.data ?? const []; if (items.isEmpty) { return _empty(); } return ListView.separated( padding: const EdgeInsets.fromLTRB(16, 4, 16, 24), itemCount: items.length, separatorBuilder: (_, __) => const SizedBox(height: 14), itemBuilder: (_, i) => _card(items[i]), ); }, ), ), ), ], ), ), ), ); } Widget _retry() => ListView(children: [ const SizedBox(height: 120), const Center( child: Text('خطا در دریافت تورنومنت‌ها', style: TextStyle(color: Colors.white70))), const SizedBox(height: 8), Center( child: TextButton( onPressed: _reload, child: const Text('تلاش مجدد', style: TextStyle(color: AppColors.gold)), ), ), ]); Widget _empty() => ListView(children: const [ SizedBox(height: 140), Icon(Icons.emoji_events_outlined, color: Colors.white24, size: 60), SizedBox(height: 12), Center( child: Text('در حال حاضر تورنومنتی برگزار نمی‌شود', style: TextStyle(color: Colors.white54))), ]); Widget _card(Tournament t) { final busy = _busyId == t.id; return GestureDetector( onTap: () => _openStandings(t), child: Container( padding: const EdgeInsets.all(14), decoration: BoxDecoration( gradient: const LinearGradient( begin: Alignment.topLeft, end: Alignment.bottomRight, colors: [Color(0xFF3A2A6E), Color(0xFF15193F), AppColors.lapisInk], ), borderRadius: BorderRadius.circular(18), border: Border.all(color: AppColors.gold, width: 1.6), boxShadow: [ BoxShadow( color: AppColors.gold.withValues(alpha: 0.18), blurRadius: 12), ], ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row(children: [ Container( padding: const EdgeInsets.all(9), decoration: const BoxDecoration( gradient: LinearGradient(colors: [AppColors.gold, AppColors.goldDark]), shape: BoxShape.circle, ), child: const Icon(Icons.emoji_events, color: AppColors.lapisInk, size: 22), ), const SizedBox(width: 10), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text(t.title, maxLines: 1, overflow: TextOverflow.ellipsis, style: const TextStyle( color: AppColors.gold, fontSize: 18, fontWeight: FontWeight.bold)), if (t.description.isNotEmpty) Text(t.description, maxLines: 1, overflow: TextOverflow.ellipsis, style: const TextStyle( color: Colors.white60, fontSize: 12)), ], ), ), _statusBadge(t.status), ]), const SizedBox(height: 12), Row(children: [ _info(Icons.emoji_events, 'جایزه کل', '${t.prizePool}', gold: true), const SizedBox(width: 8), _info(Icons.login, 'ورودی', t.entryFee == 0 ? 'رایگان' : '${t.entryFee}'), const SizedBox(width: 8), _info(Icons.people, 'شرکت‌کننده', '${t.players}'), ]), if (t.startsLocal.isNotEmpty) ...[ const SizedBox(height: 8), Row(children: [ const Icon(Icons.schedule, color: Colors.white38, size: 13), const SizedBox(width: 5), Text( t.isUpcoming ? 'شروع: ${t.startsLocal}' : 'پایان: ${t.endsLocal}', style: const TextStyle(color: Colors.white54, fontSize: 11), ), ]), ], const SizedBox(height: 12), _action(t, busy), ], ), ), ); } Widget _statusBadge(String status) { late Color c; late String label; switch (status) { case 'active': c = AppColors.success; label = 'در حال برگزاری'; break; case 'upcoming': c = const Color(0xFFE9952F); label = 'به‌زودی'; break; default: c = Colors.white38; label = 'پایان‌یافته'; } return Container( padding: const EdgeInsets.symmetric(horizontal: 9, vertical: 4), decoration: BoxDecoration( color: c.withValues(alpha: 0.18), borderRadius: BorderRadius.circular(8), border: Border.all(color: c), ), child: Text(label, style: TextStyle(color: c, fontSize: 11, fontWeight: FontWeight.bold)), ); } Widget _info(IconData icon, String label, String value, {bool gold = false}) { return Expanded( child: Container( padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 6), decoration: BoxDecoration( color: Colors.white.withValues(alpha: 0.05), borderRadius: BorderRadius.circular(10), border: Border.all(color: Colors.white.withValues(alpha: 0.1)), ), child: Column(children: [ Icon(icon, size: 16, color: gold ? AppColors.gold : Colors.white70), const SizedBox(height: 3), Text(value, style: TextStyle( color: gold ? AppColors.gold : Colors.white, fontSize: 14, fontWeight: FontWeight.bold)), Text(label, style: const TextStyle(color: Colors.white54, fontSize: 10)), ]), ), ); } Widget _action(Tournament t, bool busy) { if (t.joined) { return Column(children: [ Container( width: double.infinity, padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 10), alignment: Alignment.center, decoration: BoxDecoration( color: AppColors.success.withValues(alpha: 0.15), borderRadius: BorderRadius.circular(12), border: Border.all(color: AppColors.success), ), child: Text( t.myRank > 0 ? 'رتبه شما: ${t.myRank} • امتیاز: ${t.myPoints}' : 'ثبت‌نام شده • امتیاز: ${t.myPoints}', style: const TextStyle( color: Colors.white, fontWeight: FontWeight.bold, fontSize: 13), ), ), const SizedBox(height: 8), Row(children: [ if (t.isActive) Expanded( child: GameButton( label: 'بازی کن و امتیاز بگیر', icon: Icons.sports_esports, colors: const [AppColors.gold, AppColors.goldDark], onTap: () async { await context.push('/game/tiers'); if (context.mounted) _reload(); }, ), ) else Expanded( child: OutlinedButton.icon( style: OutlinedButton.styleFrom( side: const BorderSide(color: AppColors.gold), padding: const EdgeInsets.symmetric(vertical: 10), ), onPressed: () => _openStandings(t), icon: const Icon(Icons.leaderboard, color: AppColors.gold, size: 18), label: const Text('جدول نتایج', style: TextStyle(color: AppColors.gold)), ), ), const SizedBox(width: 8), _tableButton(t), ]), ]); } if (t.canJoin) { return Row(children: [ Expanded( child: GameButton( label: busy ? '...' : (t.entryFee == 0 ? 'ثبت‌نام رایگان' : 'ثبت‌نام (${t.entryFee} سکه)'), icon: Icons.how_to_reg, colors: const [AppColors.success, AppColors.successDark], onTap: busy ? null : () => _join(t), ), ), const SizedBox(width: 8), _tableButton(t), ]); } // پایان‌یافته و ثبت‌نام‌نشده ⇒ فقط جدول. return SizedBox( width: double.infinity, child: OutlinedButton.icon( style: OutlinedButton.styleFrom( side: const BorderSide(color: AppColors.gold), padding: const EdgeInsets.symmetric(vertical: 10), ), onPressed: () => _openStandings(t), icon: const Icon(Icons.leaderboard, color: AppColors.gold, size: 18), label: const Text('جدول نتایج', style: TextStyle(color: AppColors.gold)), ), ); } Widget _tableButton(Tournament t) => Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(12), border: Border.all(color: AppColors.gold), ), child: IconButton( tooltip: 'جدول', onPressed: () => _openStandings(t), icon: const Icon(Icons.leaderboard, color: AppColors.gold), ), ); }