import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import '../../../../core/theme/app_colors.dart'; import '../providers/referral_providers.dart'; import '../../domain/models/referral_info.dart'; class ReferralScreen extends ConsumerWidget { const ReferralScreen({super.key}); @override Widget build(BuildContext context, WidgetRef ref) { final infoAsync = ref.watch(referralInfoProvider); final isDark = Theme.of(context).brightness == Brightness.dark; final cardColor = isDark ? AppColors.surface : Colors.white; return Scaffold( backgroundColor: AppColors.background, appBar: AppBar( backgroundColor: AppColors.background, title: const Text('邀请有礼'), actions: [ IconButton( icon: const Icon(Icons.refresh), onPressed: () { ref.invalidate(referralInfoProvider); ref.invalidate(referralListProvider); ref.invalidate(pendingRewardsProvider); }, ), ], ), body: infoAsync.when( loading: () => const Center(child: CircularProgressIndicator()), error: (e, _) => Center(child: Text('加载失败: $e')), data: (info) => _ReferralBody(info: info, cardColor: cardColor), ), ); } } class _ReferralBody extends ConsumerWidget { final ReferralInfo info; final Color cardColor; const _ReferralBody({required this.info, required this.cardColor}); @override Widget build(BuildContext context, WidgetRef ref) { return ListView( padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), children: [ // ── Referral Code Card ───────────────────────────────────── _ReferralCodeCard(info: info, cardColor: cardColor), const SizedBox(height: 16), // ── Stats Row ───────────────────────────────────────────── _StatsRow(info: info, cardColor: cardColor), const SizedBox(height: 20), // ── Reward Rules ────────────────────────────────────────── _RewardRulesCard(cardColor: cardColor), const SizedBox(height: 20), // ── Referral List ───────────────────────────────────────── Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ const Text( '推荐记录', style: TextStyle(fontWeight: FontWeight.w600, fontSize: 16), ), TextButton( onPressed: () => _showReferralList(context), child: const Text('查看全部 >'), ), ], ), _ReferralPreviewList(cardColor: cardColor), const SizedBox(height: 20), // ── Reward List ─────────────────────────────────────────── Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ const Text( '待领积分', style: TextStyle(fontWeight: FontWeight.w600, fontSize: 16), ), TextButton( onPressed: () => _showRewardList(context), child: const Text('查看全部 >'), ), ], ), _RewardPreviewList(cardColor: cardColor), const SizedBox(height: 40), ], ); } void _showReferralList(BuildContext context) { Navigator.push( context, MaterialPageRoute(builder: (_) => const _ReferralListPage()), ); } void _showRewardList(BuildContext context) { Navigator.push( context, MaterialPageRoute(builder: (_) => const _RewardListPage()), ); } } // ── Referral Code Card ──────────────────────────────────────────────────────── class _ReferralCodeCard extends StatelessWidget { final ReferralInfo info; final Color cardColor; const _ReferralCodeCard({required this.info, required this.cardColor}); @override Widget build(BuildContext context) { return Card( color: cardColor, elevation: 0, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)), child: Padding( padding: const EdgeInsets.all(20), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text( '你的推荐码', style: TextStyle(color: Colors.grey, fontSize: 13), ), const SizedBox(height: 8), Row( children: [ Expanded( child: Text( info.referralCode, style: const TextStyle( fontSize: 28, fontWeight: FontWeight.bold, letterSpacing: 2, color: AppColors.primary, ), ), ), IconButton( icon: const Icon(Icons.copy, color: AppColors.primary), tooltip: '复制推荐码', onPressed: () => _copy(context, info.referralCode), ), ], ), const SizedBox(height: 12), Row( children: [ Expanded( child: OutlinedButton.icon( icon: const Icon(Icons.link, size: 18), label: const Text('复制邀请链接'), onPressed: () => _copy(context, info.shareUrl), style: OutlinedButton.styleFrom( foregroundColor: AppColors.primary, side: const BorderSide(color: AppColors.primary), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(10)), ), ), ), const SizedBox(width: 8), Expanded( child: FilledButton.icon( icon: const Icon(Icons.share, size: 18), label: const Text('分享'), onPressed: () => _share(context, info), style: FilledButton.styleFrom( backgroundColor: AppColors.primary, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(10)), ), ), ), ], ), ], ), ), ); } void _copy(BuildContext context, String text) { Clipboard.setData(ClipboardData(text: text)); ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('已复制到剪贴板'), duration: Duration(seconds: 2)), ); } void _share(BuildContext context, ReferralInfo info) { // For a full implementation, use share_plus package // For now, copy the share text final text = '邀请你使用 IT0 智能运维平台,注册即可获得积分奖励!\n推荐码:${info.referralCode}\n链接:${info.shareUrl}'; _copy(context, text); } } // ── Stats Row ───────────────────────────────────────────────────────────────── class _StatsRow extends StatelessWidget { final ReferralInfo info; final Color cardColor; const _StatsRow({required this.info, required this.cardColor}); @override Widget build(BuildContext context) { return Row( children: [ _StatCard( cardColor: cardColor, label: '已推荐', value: '${info.directCount}', unit: '人', color: const Color(0xFF6366F1), ), const SizedBox(width: 10), _StatCard( cardColor: cardColor, label: '已激活', value: '${info.activeCount}', unit: '人', color: const Color(0xFF10B981), ), const SizedBox(width: 10), _StatCard( cardColor: cardColor, label: '待领积分', value: info.pendingCreditFormatted, unit: '', color: const Color(0xFFF59E0B), ), ], ); } } class _StatCard extends StatelessWidget { final Color cardColor; final String label; final String value; final String unit; final Color color; const _StatCard({ required this.cardColor, required this.label, required this.value, required this.unit, required this.color, }); @override Widget build(BuildContext context) { return Expanded( child: Card( color: cardColor, elevation: 0, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)), child: Padding( padding: const EdgeInsets.symmetric(vertical: 16, horizontal: 12), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text(label, style: const TextStyle(fontSize: 12, color: Colors.grey)), const SizedBox(height: 4), RichText( text: TextSpan( children: [ TextSpan( text: value, style: TextStyle( fontSize: 22, fontWeight: FontWeight.bold, color: color, ), ), if (unit.isNotEmpty) TextSpan( text: unit, style: TextStyle( fontSize: 13, color: color.withAlpha(180)), ), ], ), ), ], ), ), ), ); } } // ── Reward Rules Card ───────────────────────────────────────────────────────── class _RewardRulesCard extends StatelessWidget { final Color cardColor; const _RewardRulesCard({required this.cardColor}); @override Widget build(BuildContext context) { return Card( color: cardColor, elevation: 0, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)), child: Padding( padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Row( children: [ Icon(Icons.card_giftcard, color: Color(0xFFF59E0B), size: 20), SizedBox(width: 6), Text( '奖励规则', style: TextStyle(fontWeight: FontWeight.w600, fontSize: 15), ), ], ), const SizedBox(height: 12), _RuleItem( icon: Icons.star_rounded, color: const Color(0xFF6366F1), text: '推荐 Pro 套餐:你获得 \$15 积分,对方获得 \$5 积分', ), const SizedBox(height: 8), _RuleItem( icon: Icons.star_rounded, color: const Color(0xFF7C3AED), text: '推荐 Enterprise 套餐:你获得 \$50 积分,对方获得 \$20 积分', ), const SizedBox(height: 8), _RuleItem( icon: Icons.repeat_rounded, color: const Color(0xFF10B981), text: '对方续订后,你持续获得每月付款额 10% 的积分,最长 12 个月', ), const SizedBox(height: 8), _RuleItem( icon: Icons.account_balance_wallet_outlined, color: const Color(0xFFF59E0B), text: '积分自动抵扣你的下期账单', ), ], ), ), ); } } class _RuleItem extends StatelessWidget { final IconData icon; final Color color; final String text; const _RuleItem({required this.icon, required this.color, required this.text}); @override Widget build(BuildContext context) { return Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ Icon(icon, color: color, size: 16), const SizedBox(width: 8), Expanded( child: Text(text, style: const TextStyle(fontSize: 13, height: 1.4)), ), ], ); } } // ── Preview Lists ───────────────────────────────────────────────────────────── class _ReferralPreviewList extends ConsumerWidget { final Color cardColor; const _ReferralPreviewList({required this.cardColor}); @override Widget build(BuildContext context, WidgetRef ref) { final async = ref.watch(referralListProvider); return async.when( loading: () => const SizedBox( height: 60, child: Center(child: CircularProgressIndicator()), ), error: (_, __) => const SizedBox.shrink(), data: (result) { if (result.items.isEmpty) { return Card( color: cardColor, elevation: 0, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)), child: const Padding( padding: EdgeInsets.all(20), child: Center( child: Text( '暂无推荐记录,分享推荐码邀请好友吧', style: TextStyle(color: Colors.grey, fontSize: 13), ), ), ), ); } final preview = result.items.take(3).toList(); return Card( color: cardColor, elevation: 0, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)), clipBehavior: Clip.antiAlias, child: Column( children: preview.map((item) => _ReferralTile(item: item)).toList(), ), ); }, ); } } class _ReferralTile extends StatelessWidget { final ReferralItem item; const _ReferralTile({required this.item}); @override Widget build(BuildContext context) { final statusColor = item.isActive ? const Color(0xFF10B981) : item.status == 'EXPIRED' ? Colors.grey : const Color(0xFFF59E0B); final statusLabel = switch (item.status) { 'PENDING' => '待付款', 'ACTIVE' => '已激活', 'REWARDED' => '已奖励', 'EXPIRED' => '已过期', _ => item.status, }; return ListTile( leading: CircleAvatar( backgroundColor: statusColor.withAlpha(30), child: Icon( item.isActive ? Icons.check_circle : Icons.pending, color: statusColor, size: 20, ), ), title: Text( item.referredTenantId.length > 8 ? '${item.referredTenantId.substring(0, 8)}...' : item.referredTenantId, style: const TextStyle(fontSize: 14, fontWeight: FontWeight.w500), ), subtitle: Text( '注册于 ${_formatDate(item.registeredAt)}', style: const TextStyle(fontSize: 12), ), trailing: Container( padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), decoration: BoxDecoration( color: statusColor.withAlpha(20), borderRadius: BorderRadius.circular(20), ), child: Text( statusLabel, style: TextStyle( fontSize: 12, color: statusColor, fontWeight: FontWeight.w500), ), ), ); } String _formatDate(DateTime dt) => '${dt.year}-${dt.month.toString().padLeft(2, '0')}-${dt.day.toString().padLeft(2, '0')}'; } class _RewardPreviewList extends ConsumerWidget { final Color cardColor; const _RewardPreviewList({required this.cardColor}); @override Widget build(BuildContext context, WidgetRef ref) { final async = ref.watch(pendingRewardsProvider); return async.when( loading: () => const SizedBox( height: 60, child: Center(child: CircularProgressIndicator())), error: (_, __) => const SizedBox.shrink(), data: (result) { if (result.items.isEmpty) { return Card( color: cardColor, elevation: 0, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)), child: const Padding( padding: EdgeInsets.all(20), child: Center( child: Text( '暂无待领积分', style: TextStyle(color: Colors.grey, fontSize: 13), ), ), ), ); } final preview = result.items.take(3).toList(); return Card( color: cardColor, elevation: 0, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)), clipBehavior: Clip.antiAlias, child: Column( children: preview .map((item) => _RewardTile(item: item)) .toList(), ), ); }, ); } } class _RewardTile extends StatelessWidget { final RewardItem item; const _RewardTile({required this.item}); @override Widget build(BuildContext context) { return ListTile( leading: CircleAvatar( backgroundColor: const Color(0xFFF59E0B).withAlpha(30), child: const Icon(Icons.attach_money, color: Color(0xFFF59E0B), size: 20), ), title: Text( item.amountFormatted, style: const TextStyle( fontSize: 16, fontWeight: FontWeight.bold, color: Color(0xFF10B981)), ), subtitle: Text(item.triggerLabel, style: const TextStyle(fontSize: 12)), trailing: Container( padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), decoration: BoxDecoration( color: const Color(0xFFF59E0B).withAlpha(20), borderRadius: BorderRadius.circular(20), ), child: const Text( '待抵扣', style: TextStyle( fontSize: 12, color: Color(0xFFF59E0B), fontWeight: FontWeight.w500), ), ), ); } } // ── Full list pages ─────────────────────────────────────────────────────────── class _ReferralListPage extends ConsumerWidget { const _ReferralListPage(); @override Widget build(BuildContext context, WidgetRef ref) { final async = ref.watch(referralListProvider); return Scaffold( appBar: AppBar(title: const Text('推荐记录')), body: async.when( loading: () => const Center(child: CircularProgressIndicator()), error: (e, _) => Center(child: Text('加载失败: $e')), data: (result) => result.items.isEmpty ? const Center(child: Text('暂无推荐记录')) : ListView.separated( itemCount: result.items.length, separatorBuilder: (_, __) => const Divider(height: 1), itemBuilder: (_, i) => _ReferralTile(item: result.items[i]), ), ), ); } } class _RewardListPage extends ConsumerWidget { const _RewardListPage(); @override Widget build(BuildContext context, WidgetRef ref) { final async = ref.watch(allRewardsProvider); return Scaffold( appBar: AppBar(title: const Text('奖励历史')), body: async.when( loading: () => const Center(child: CircularProgressIndicator()), error: (e, _) => Center(child: Text('加载失败: $e')), data: (result) => result.items.isEmpty ? const Center(child: Text('暂无奖励记录')) : ListView.separated( itemCount: result.items.length, separatorBuilder: (_, __) => const Divider(height: 1), itemBuilder: (_, i) => _RewardTile(item: result.items[i]), ), ), ); } }