import 'package:flutter/material.dart'; import 'package:flutter/services.dart' show LengthLimitingTextInputFormatter; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:go_router/go_router.dart'; import 'package:random_avatar/random_avatar.dart'; import '../../../../core/theme/app_theme.dart'; import '../../../../core/widgets/game_ui.dart'; import '../../../../core/widgets/rank_badge.dart'; import '../../../wallet/presentation/bloc/wallet_bloc.dart'; import '../../../wallet/presentation/bloc/wallet_event.dart'; import '../../domain/entities/profile_entity.dart'; import '../bloc/profile_bloc.dart'; import '../bloc/profile_event.dart'; import '../bloc/profile_state.dart'; import '../bloc/profile_status.dart'; /// صفحه‌ی پروفایل: نام، آواتار (قابل ویرایش)، سطح، جام و آمارِ بازی (ویژه‌ی VIP). class ProfileScreen extends StatelessWidget { const ProfileScreen({super.key}); @override Widget build(BuildContext context) { return Scaffold( body: GameBackground( child: SafeArea( child: BlocConsumer( listenWhen: (a, b) => a.saveStatus != b.saveStatus, listener: (context, state) { final s = state.saveStatus; if (s is ProfileSaveSuccess) { context.read().add(LoadWalletEvent()); } else if (s is ProfileSaveError) { ScaffoldMessenger.of( context, ).showSnackBar(SnackBar(content: Text(s.message))); } }, builder: (context, state) { final st = state.loadStatus; if (st is ProfileLoadError) { return Center( child: Column( mainAxisSize: MainAxisSize.min, children: [ Text( st.message, style: const TextStyle(color: Colors.white70), ), const SizedBox(height: 12), GameButton( label: 'تلاش دوباره', onTap: () => context.read().add( LoadProfileEvent(), ), ), ], ), ); } if (st is! ProfileLoadLoaded) { return const Center( child: CircularProgressIndicator(color: AppColors.gold), ); } return _content(context, st.profile); }, ), ), ), ); } Future _editProfile(BuildContext context, ProfileEntity d) async { final result = await showModalBottomSheet>( context: context, isScrollControlled: true, backgroundColor: Colors.transparent, builder: (_) => _EditProfileSheet(name: d.name, avatar: d.avatar), ); if (result == null || !context.mounted) return; context.read().add( SaveProfileEvent(result['name']!, result['avatar']!), ); } Widget _content(BuildContext context, ProfileEntity d) { return SingleChildScrollView( padding: const EdgeInsets.all(16), child: Column( children: [ Row( children: [ const AppBackButton(), const Spacer(), const GlowText('پروفایل', size: 24), const Spacer(), const SizedBox(width: 48), ], ), const SizedBox(height: 8), GamePanel( child: Column( children: [ Stack( children: [ Container( padding: const EdgeInsets.all(6), decoration: BoxDecoration( shape: BoxShape.circle, border: Border.all(color: AppColors.gold, width: 2.5), ), child: RandomAvatar(d.avatar, height: 92, width: 92), ), Positioned( bottom: 0, right: 0, child: GestureDetector( onTap: () => _editProfile(context, d), child: Container( padding: const EdgeInsets.all(6), decoration: const BoxDecoration( shape: BoxShape.circle, gradient: LinearGradient( colors: [Color(0xFFFFD54F), AppColors.goldDark], ), ), child: const Icon( Icons.edit, color: AppColors.bg, size: 18, ), ), ), ), ], ), const SizedBox(height: 10), Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Flexible(child: GlowText(d.name, size: 22)), if (d.vip) ...[const SizedBox(width: 8), const _VipBadge()], ], ), const SizedBox(height: 8), RankBadge(tier: d.rankTier, points: d.rankPoints), if (d.mobile.isNotEmpty) Text( d.mobile, style: const TextStyle(color: Colors.white38, fontSize: 12), ), const SizedBox(height: 14), Row( children: [ Expanded( child: _MiniStat( icon: Icons.star, label: 'سطح', value: '${d.level}', ), ), Expanded( child: _MiniStat( icon: Icons.emoji_events, label: 'جام', value: '${d.trophies}', ), ), ], ), const SizedBox(height: 10), ClipRRect( borderRadius: BorderRadius.circular(5), child: LinearProgressIndicator( value: d.xpNext == 0 ? 0 : d.xpInto / d.xpNext, minHeight: 8, backgroundColor: Colors.white10, valueColor: const AlwaysStoppedAnimation(AppColors.gold), ), ), Padding( padding: const EdgeInsets.only(top: 4), child: Text( '${d.xpInto} / ${d.xpNext} XP', style: const TextStyle(color: Colors.white38, fontSize: 11), ), ), ], ), ), const SizedBox(height: 16), const Align( alignment: Alignment.centerRight, child: GlowText('آمار بازی', size: 18), ), const SizedBox(height: 8), _statsSection(context, d), const SizedBox(height: 16), Align( alignment: Alignment.center, child: TextButton.icon( onPressed: () => context.push('/terms'), icon: const Icon(Icons.gavel, color: AppColors.gold, size: 18), label: const Text( 'شرایط و قوانین', style: TextStyle(color: AppColors.gold, fontSize: 14), ), ), ), ], ), ); } Widget _statsSection(BuildContext context, ProfileEntity d) { final s = d.stats; final rows = [ _StatRow('بازی کل', s?.games, Icons.casino), _StatRow('برد کل', s?.wins, Icons.thumb_up), _StatRow('باخت کل', s?.losses, Icons.thumb_down), _StatRow('کُت کردن', s?.kotMade, Icons.flash_on), _StatRow('کُت شدن', s?.kotReceived, Icons.flash_off), _StatRow('بریدن', s?.cuts, Icons.bolt), _StatRow('دست حاکم', s?.hakemCount, Icons.workspace_premium), ]; final panel = GamePanel(child: Column(children: rows)); if (d.vip) return panel; return Stack( children: [ Opacity(opacity: 0.35, child: IgnorePointer(child: panel)), Positioned.fill( child: Container( decoration: BoxDecoration( color: Colors.black.withValues(alpha: 0.45), borderRadius: BorderRadius.circular(16), border: Border.all(color: AppColors.goldDark), ), child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ const Icon(Icons.lock, color: AppColors.gold, size: 36), const SizedBox(height: 8), const Padding( padding: EdgeInsets.symmetric(horizontal: 24), child: Text( 'مشاهده‌ی آمار ویژه‌ی کاربران VIP است', textAlign: TextAlign.center, style: TextStyle(color: Colors.white, fontSize: 14), ), ), const SizedBox(height: 12), GameButton( label: 'تهیه اشتراک VIP', icon: Icons.workspace_premium, colors: const [Color(0xFFFFC107), AppColors.goldDark], onTap: () async { await context.push('/vip'); if (context.mounted) { context.read().add(LoadProfileEvent()); } }, ), ], ), ), ), ], ); } } class _StatRow extends StatelessWidget { final String label; final Object? value; final IconData icon; const _StatRow(this.label, this.value, this.icon); @override Widget build(BuildContext context) { return Padding( padding: const EdgeInsets.symmetric(vertical: 7), child: Row( children: [ Icon(icon, color: AppColors.gold, size: 20), const SizedBox(width: 10), Text( label, style: const TextStyle(color: Colors.white, fontSize: 15), ), const Spacer(), Text( '${value ?? '—'}', style: const TextStyle( color: AppColors.gold, fontSize: 16, fontWeight: FontWeight.bold, ), ), ], ), ); } } class _MiniStat extends StatelessWidget { final IconData icon; final String label; final String value; const _MiniStat({ required this.icon, required this.label, required this.value, }); @override Widget build(BuildContext context) { return Column( children: [ Icon(icon, color: AppColors.gold, size: 22), const SizedBox(height: 2), Text( value, style: const TextStyle( color: Colors.white, fontSize: 18, fontWeight: FontWeight.bold, ), ), Text( label, style: const TextStyle(color: Colors.white54, fontSize: 12), ), ], ); } } class _VipBadge extends StatelessWidget { const _VipBadge(); @override Widget build(BuildContext context) { return Container( padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 3), decoration: BoxDecoration( gradient: const LinearGradient( colors: [Color(0xFFFFD54F), AppColors.goldDark], ), borderRadius: BorderRadius.circular(8), ), child: const Text( 'VIP', style: TextStyle( color: AppColors.bg, fontWeight: FontWeight.bold, fontSize: 12, ), ), ); } } /// شیتِ ویرایش نام و آواتار (با تأیید، مقدار جدید را برمی‌گرداند). class _EditProfileSheet extends StatefulWidget { final String name; final String avatar; const _EditProfileSheet({required this.name, required this.avatar}); @override State<_EditProfileSheet> createState() => _EditProfileSheetState(); } class _EditProfileSheetState extends State<_EditProfileSheet> { late final TextEditingController _name; late final List _seeds; late String _selected; @override void initState() { super.initState(); _name = TextEditingController(text: widget.name); _seeds = List.generate(12, (i) => 'hakem-${i + 1}'); if (!_seeds.contains(widget.avatar)) _seeds.insert(0, widget.avatar); _selected = widget.avatar; } @override void dispose() { _name.dispose(); super.dispose(); } bool get _valid => _name.text.trim().length >= 2; @override Widget build(BuildContext context) { return SafeArea( top: false, child: Padding( padding: EdgeInsets.only( bottom: MediaQuery.of(context).viewInsets.bottom, ), child: Container( decoration: const BoxDecoration( color: AppColors.bgDark, borderRadius: BorderRadius.vertical(top: Radius.circular(20)), border: Border(top: BorderSide(color: AppColors.gold, width: 2)), ), padding: const EdgeInsets.all(18), child: SingleChildScrollView( child: Column( mainAxisSize: MainAxisSize.min, children: [ const GlowText('ویرایش پروفایل', size: 20), const SizedBox(height: 14), Container( padding: const EdgeInsets.all(4), decoration: BoxDecoration( shape: BoxShape.circle, border: Border.all(color: AppColors.gold, width: 2), ), child: RandomAvatar(_selected, height: 72, width: 72), ), const SizedBox(height: 12), TextField( controller: _name, textAlign: TextAlign.center, maxLength: 20, inputFormatters: [LengthLimitingTextInputFormatter(20)], decoration: const InputDecoration( hintText: 'نام نمایشی (۲ تا ۲۰ حرف)', counterText: '', ), onChanged: (_) => setState(() {}), ), const SizedBox(height: 10), const Align( alignment: Alignment.centerRight, child: Text( 'انتخاب آواتار', style: TextStyle(color: AppColors.gold), ), ), const SizedBox(height: 8), GridView.count( crossAxisCount: 4, shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), mainAxisSpacing: 10, crossAxisSpacing: 10, children: [ for (final s in _seeds) GestureDetector( onTap: () => setState(() => _selected = s), child: Container( decoration: BoxDecoration( shape: BoxShape.circle, color: AppColors.panel, border: Border.all( color: _selected == s ? AppColors.gold : Colors.transparent, width: 2.5, ), ), child: RandomAvatar(s), ), ), ], ), const SizedBox(height: 16), GameButton( label: 'تأیید', width: double.infinity, colors: const [AppColors.success, AppColors.successDark], onTap: _valid ? () => Navigator.pop(context, { 'name': _name.text.trim(), 'avatar': _selected, }) : null, ), ], ), ), ), ), ); } }