import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:go_router/go_router.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 '../../domain/entities/shop_entities.dart'; import '../bloc/shop_bloc.dart'; import '../bloc/shop_event.dart'; import '../bloc/shop_state.dart'; import '../bloc/shop_status.dart'; /// فروشگاه با تب‌های سکه/بلیط/کارت/تجهیزات/VIP. class ShopScreen extends StatelessWidget { const ShopScreen({super.key}); @override Widget build(BuildContext context) { return DefaultTabController( length: 5, child: Scaffold( backgroundColor: Colors.transparent, body: GameBackground( child: BlocConsumer( listenWhen: (a, b) => a.actionStatus != b.actionStatus, listener: (context, state) { final s = state.actionStatus; if (s is ActionSuccess) { context.read().add(LoadWalletEvent()); ScaffoldMessenger.of(context) .showSnackBar(SnackBar(content: Text(s.message))); } else if (s is ActionError) { ScaffoldMessenger.of(context) .showSnackBar(SnackBar(content: Text(s.message))); } }, builder: (context, state) { return Column( children: [ _header(context), Expanded( child: Container( margin: const EdgeInsets.fromLTRB(8, 0, 8, 8), decoration: BoxDecoration( gradient: const LinearGradient( begin: Alignment.topCenter, end: Alignment.bottomCenter, colors: [Color(0xFF4A0C16), Color(0xFF2A0710)], ), borderRadius: BorderRadius.circular(16), border: Border.all(color: AppColors.goldDark, width: 1.5), ), child: Column( children: [ const _ShopTabs(), Expanded(child: _body(context, state.loadStatus)), ], ), ), ), ], ); }, ), ), ), ); } Widget _body(BuildContext context, ShopLoadStatus status) { if (status is ShopLoaded) { final d = status.data; return TabBarView( children: [ _CoinsTab(packages: d.coinPackages), _TicketsTab(packages: d.ticketPackages), _CardsTab(data: d), _BoostersTab(boosters: d.boosters), _VipTab(packages: d.vipPackages), ], ); } if (status is ShopLoadError) { return Center( child: Column(mainAxisSize: MainAxisSize.min, children: [ Text(status.message), TextButton( onPressed: () => context.read().add(LoadShopEvent()), child: const Text('تلاش مجدد'), ), ]), ); } return const Center(child: CircularProgressIndicator(color: AppColors.gold)); } Widget _header(BuildContext context) { return Padding( padding: const EdgeInsets.all(8), child: Row(children: [ GestureDetector( onTap: () => context.pop(), child: Container( width: 46, height: 46, decoration: BoxDecoration( color: AppColors.panel, borderRadius: BorderRadius.circular(12), border: Border.all(color: AppColors.gold, width: 1.5), ), child: const Icon(Icons.arrow_back, color: AppColors.gold), ), ), const Spacer(), BlocBuilder( builder: (context, s) { final w = s.walletStatus is WalletLoaded ? (s.walletStatus as WalletLoaded).wallet : null; return Row(children: [ StatChip( icon: Icons.confirmation_number, value: '${w?.tickets ?? 0}'), const SizedBox(width: 8), StatChip(icon: Icons.monetization_on, value: '${w?.coins ?? 0}'), ]); }, ), ]), ); } } class _ShopTabs extends StatelessWidget { const _ShopTabs(); @override Widget build(BuildContext context) { return const TabBar( indicator: BoxDecoration( gradient: LinearGradient( begin: Alignment.topCenter, end: Alignment.bottomCenter, colors: [Color(0xFFC62828), Color(0xFF7B0E14)], ), borderRadius: BorderRadius.vertical(top: Radius.circular(12)), ), indicatorSize: TabBarIndicatorSize.tab, labelColor: AppColors.gold, unselectedLabelColor: Colors.white60, labelStyle: TextStyle(fontWeight: FontWeight.bold), dividerColor: Colors.transparent, isScrollable: true, tabAlignment: TabAlignment.center, tabs: [ Tab(text: 'سکه'), Tab(text: 'بلیط'), Tab(text: 'کارت'), Tab(text: 'تجهیزات'), Tab(text: 'VIP'), ], ); } } // ===== تب‌ها ===== class _CoinsTab extends StatelessWidget { final List packages; const _CoinsTab({required this.packages}); @override Widget build(BuildContext context) { return _grid( note: 'با داشتن اشتراک VIP در هر خرید ۱۰٪ سکه اضافه هدیه می‌گیرید.', children: [ _ItemCard( title: 'سکه رایگان', glowColor: const Color(0xFF1B5E20), icon: Icons.card_giftcard, subtitle: 'با دیدن تبلیغ', action: _PriceButton( label: 'رایگان', green: true, onTap: () => context.read().add(AdRewardEvent()), ), ), for (final p in packages) _ItemCard( title: p.title, glowColor: const Color(0xFF1B5E20), icon: Icons.savings, ribbon: p.bonusPct > 0 ? '+${p.bonusPct}٪' : null, subtitle: '${p.coins} سکه${p.vipDays > 0 ? ' + ${p.vipDays} روز VIP' : ''}', action: _PriceButton( label: '${p.priceToman} تومان', onTap: () => context.read().add(PurchaseEvent('coin', p.id)), ), ), ], ); } } class _TicketsTab extends StatelessWidget { final List packages; const _TicketsTab({required this.packages}); @override Widget build(BuildContext context) { return _grid( note: 'با خرید بلیط می‌توانید درخواست بر زدن مجدد در بازی‌ها انجام دهید.', children: [ for (final p in packages) _ItemCard( title: p.title, glowColor: const Color(0xFF8E1B7A), icon: Icons.confirmation_number, subtitle: '${p.tickets} بلیط', action: _PriceButton( label: '${p.priceToman} تومان', onTap: () => context.read().add(PurchaseEvent('ticket', p.id)), ), ), ], ); } } class _BoostersTab extends StatelessWidget { final List boosters; const _BoostersTab({required this.boosters}); @override Widget build(BuildContext context) { return _grid( note: 'با بسته‌های تجربه، چند برابر XP بگیرید و سریع‌تر بالا بروید.', children: [ for (final b in boosters) _ItemCard( title: b.title, glowColor: const Color(0xFF1E3A8A), icon: Icons.bolt, subtitle: 'تجربه ×${b.multiplier} — ${b.hours} ساعت', action: _PriceButton( label: '${b.priceToman} تومان', onTap: () => context.read().add(PurchaseEvent('booster', b.id)), ), ), ], ); } } class _VipTab extends StatelessWidget { final List packages; const _VipTab({required this.packages}); @override Widget build(BuildContext context) { return _grid( note: 'با VIP: میز خصوصی نامحدود، آمار کامل و ۱۰٪ سکه‌ی هدیه.', children: [ for (final p in packages) _ItemCard( title: p.title, glowColor: const Color(0xFF8A6D00), icon: Icons.workspace_premium, ribbon: p.months >= 6 ? 'بهترین' : null, subtitle: '${p.months} ماه اشتراک', action: _PriceButton( label: '${p.priceToman} تومان', onTap: () => context.read().add(PurchaseEvent('vip', p.id)), ), ), ], ); } } class _CardsTab extends StatelessWidget { final ShopData data; const _CardsTab({required this.data}); @override Widget build(BuildContext context) { return _grid( note: 'با اسکین کارت‌های متنوع حال‌وهوای بازی را عوض کن.', children: [ for (final c in data.cardSkins) _ItemCard( title: c.title, glowColor: const Color(0xFF0E3C73), icon: Icons.style, subtitle: c.priceCoins > 0 ? '${c.priceCoins} سکه' : 'پیش‌فرض', action: _cardAction(context, c, data), ), ], ); } Widget _cardAction(BuildContext context, CardSkin c, ShopData d) { if (d.selectedCard == c.id) { return const _PriceButton(label: 'انتخاب شده', disabled: true); } if (d.owns(c.id)) { return _PriceButton( label: 'انتخاب', green: true, onTap: () => context.read().add(SelectCardEvent(c.id)), ); } return _PriceButton( label: '${c.priceCoins} سکه', green: true, coin: true, onTap: () => context.read().add(BuyCardEvent(c.id)), ); } } Widget _grid({required String note, required List children}) { return Column( children: [ Padding( padding: const EdgeInsets.fromLTRB(16, 12, 16, 6), child: Text(note, textAlign: TextAlign.center, style: const TextStyle(color: AppColors.gold, fontSize: 13)), ), Expanded( child: GridView.count( crossAxisCount: 2, padding: const EdgeInsets.all(12), childAspectRatio: 0.74, mainAxisSpacing: 12, crossAxisSpacing: 12, children: children, ), ), ], ); } // ===== ویجت‌های کارت آیتم ===== class _ItemCard extends StatelessWidget { final String title; final IconData icon; final Color glowColor; final String subtitle; final String? ribbon; final Widget action; const _ItemCard({ required this.title, required this.icon, required this.glowColor, required this.subtitle, required this.action, this.ribbon, }); @override Widget build(BuildContext context) { final card = Container( padding: const EdgeInsets.all(8), decoration: BoxDecoration( gradient: const LinearGradient( begin: Alignment.topCenter, end: Alignment.bottomCenter, colors: [Color(0xFF6E1322), Color(0xFF3A0A12)], ), borderRadius: BorderRadius.circular(14), border: Border.all(color: AppColors.gold, width: 1.6), boxShadow: const [ BoxShadow(color: Colors.black54, blurRadius: 8, offset: Offset(0, 4)), ], ), child: Column( children: [ Text(title, maxLines: 1, overflow: TextOverflow.ellipsis, style: const TextStyle( color: AppColors.gold, fontWeight: FontWeight.bold)), const SizedBox(height: 6), Expanded(child: _GlowArt(color: glowColor, icon: icon)), const SizedBox(height: 4), Text(subtitle, maxLines: 1, overflow: TextOverflow.ellipsis, style: const TextStyle(color: Colors.white70, fontSize: 11)), const SizedBox(height: 6), SizedBox(width: double.infinity, child: action), ], ), ); if (ribbon == null) return card; return Stack(clipBehavior: Clip.none, children: [ card, Positioned( top: 8, left: -22, child: Transform.rotate( angle: -0.7, child: Container( padding: const EdgeInsets.symmetric(horizontal: 26, vertical: 3), color: const Color(0xFF2E7D32), child: Text(ribbon!, style: const TextStyle( color: Colors.white, fontSize: 11, fontWeight: FontWeight.bold)), ), ), ), ]); } } class _GlowArt extends StatelessWidget { final Color color; final IconData icon; const _GlowArt({required this.color, required this.icon}); @override Widget build(BuildContext context) { return Container( width: double.infinity, decoration: BoxDecoration( borderRadius: BorderRadius.circular(10), gradient: RadialGradient( colors: [color, Colors.black.withValues(alpha: 0.85)], radius: 0.9, ), border: Border.all(color: Colors.black26), ), child: Center(child: Icon(icon, size: 44, color: AppColors.gold)), ); } } class _PriceButton extends StatelessWidget { final String label; final VoidCallback? onTap; final bool green; final bool coin; final bool disabled; const _PriceButton({ required this.label, this.onTap, this.green = false, this.coin = false, this.disabled = false, }); @override Widget build(BuildContext context) { final busy = context.select((ShopBloc c) => c.state.busy); final colors = disabled ? const [Color(0xFF555555), Color(0xFF333333)] : green ? const [Color(0xFF3FA34D), Color(0xFF1B5E20)] : const [Color(0xFFD83A4A), Color(0xFF8E0E1B)]; return Opacity( opacity: disabled ? 0.85 : 1, child: GestureDetector( onTap: (disabled || busy) ? null : onTap, child: Container( height: 36, alignment: Alignment.center, padding: const EdgeInsets.symmetric(horizontal: 6), decoration: BoxDecoration( gradient: LinearGradient( begin: Alignment.topCenter, end: Alignment.bottomCenter, colors: colors, ), borderRadius: BorderRadius.circular(10), border: Border.all(color: AppColors.gold, width: 1.2), ), child: Row(mainAxisSize: MainAxisSize.min, children: [ if (coin) ...[ const Icon(Icons.monetization_on, color: AppColors.gold, size: 16), const SizedBox(width: 4), ], Flexible( child: Text(label, maxLines: 1, overflow: TextOverflow.ellipsis, style: const TextStyle( color: Colors.white, fontSize: 13, fontWeight: FontWeight.bold)), ), ]), ), ), ); } }