import 'package:flutter/material.dart'; import 'package:shadcn_ui/shadcn_ui.dart'; import 'package:provider/provider.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:lucide_icons_flutter/lucide_icons.dart'; import '../../../core/theme/app_color_scheme.dart'; import '../../../core/theme/app_spacing.dart'; import '../../../providers/auth_provider.dart'; import 'kyc_page.dart'; import '../../../providers/theme_provider.dart'; import '../auth/login_page.dart'; import 'welfare_center_page.dart'; /// 我的页面 - 匹配 .pen 设计稿 class MinePage extends StatefulWidget { const MinePage({super.key}); @override State createState() => _MinePageState(); } class _MinePageState extends State with AutomaticKeepAliveClientMixin { @override bool get wantKeepAlive => true; @override Widget build(BuildContext context) { super.build(context); final colorScheme = Theme.of(context).colorScheme; return Scaffold( backgroundColor: colorScheme.background, body: Consumer( builder: (context, auth, _) { return SingleChildScrollView( padding: EdgeInsets.fromLTRB( AppSpacing.md, AppSpacing.md, AppSpacing.md, AppSpacing.xl + AppSpacing.md, ), child: Column( children: [ _ProfileCard(user: auth.user), SizedBox(height: AppSpacing.sm), _MenuGroup1( kycStatus: auth.user?.kycStatus ?? 0, onShowComingSoon: _showComingSoon, ), SizedBox(height: AppSpacing.sm), _MenuGroup2(onShowAbout: _showAboutDialog), SizedBox(height: AppSpacing.lg), _LogoutButton(onLogout: () => _handleLogout(auth)), SizedBox(height: AppSpacing.md), Text( 'System Build v1.0.0', style: GoogleFonts.inter( fontSize: 11, fontWeight: FontWeight.normal, color: colorScheme.onSurfaceVariant.withOpacity(0.5), ), ), ], ), ); }, ), ); } void _showComingSoon(String feature) { showShadDialog( context: context, builder: (context) => ShadDialog.alert( title: Row( children: [ Icon(Icons.construction, color: AppColorScheme.warning, size: 20), SizedBox(width: AppSpacing.sm), const Text('功能开发中'), ], ), description: Text('$feature功能正在开发中,敬请期待~'), actions: [ ShadButton( child: const Text('知道了'), onPressed: () => Navigator.of(context).pop(), ), ], ), ); } void _showAboutDialog() { final colorScheme = Theme.of(context).colorScheme; showShadDialog( context: context, builder: (context) => ShadDialog( title: Row( children: [ _AvatarCircle(radius: 20, fontSize: 16), SizedBox(width: AppSpacing.sm + AppSpacing.xs), const Text('模拟所'), ], ), child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( '虚拟货币模拟交易平台', style: TextStyle(color: colorScheme.onSurfaceVariant), ), SizedBox(height: AppSpacing.md), _InfoRow(icon: Icons.code, text: '版本: 1.0.0'), SizedBox(height: AppSpacing.sm), _InfoRow( icon: Icons.favorite, text: 'Built with Flutter & Material Design 3'), ], ), actions: [ ShadButton( child: const Text('确定'), onPressed: () => Navigator.of(context).pop(), ), ], ), ); } void _handleLogout(AuthProvider auth) { showShadDialog( context: context, builder: (ctx) => ShadDialog.alert( title: const Text('确认退出'), description: const Text('确定要退出登录吗?'), actions: [ ShadButton.outline( child: const Text('取消'), onPressed: () => Navigator.of(ctx).pop(), ), ShadButton.destructive( child: const Text('退出'), onPressed: () async { Navigator.of(ctx).pop(); await auth.logout(); if (ctx.mounted) { Navigator.of(ctx).pushAndRemoveUntil( MaterialPageRoute(builder: (_) => const LoginPage()), (route) => false, ); } }, ), ], ), ); } } // ============================================================ // Profile Card // ============================================================ /// 用户资料卡片 - 头像 + 用户名 + 徽章 + chevron class _ProfileCard extends StatelessWidget { final dynamic user; const _ProfileCard({required this.user}); @override Widget build(BuildContext context) { final colorScheme = Theme.of(context).colorScheme; final isDark = Theme.of(context).brightness == Brightness.dark; return Container( width: double.infinity, padding: const EdgeInsets.all(20), decoration: BoxDecoration( color: isDark ? colorScheme.surfaceContainer : colorScheme.surfaceContainerHigh, borderRadius: BorderRadius.circular(AppRadius.lg), border: Border.all( color: colorScheme.outlineVariant.withOpacity(0.15), ), ), child: Row( children: [ // Avatar _AvatarCircle( radius: 24, fontSize: 18, text: user?.avatarText, ), const SizedBox(width: 12), // Name + badge column Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( user?.username ?? '未登录', style: GoogleFonts.inter( fontSize: 16, fontWeight: FontWeight.w600, color: colorScheme.onSurface, ), ), const SizedBox(height: 4), Text( '普通用户', style: GoogleFonts.inter( fontSize: 10, fontWeight: FontWeight.normal, color: colorScheme.onSurfaceVariant, ), ), ], ), ), // Chevron Icon( LucideIcons.chevronRight, size: 16, color: colorScheme.onSurfaceVariant, ), ], ), ); } } /// 圆形头像组件 class _AvatarCircle extends StatelessWidget { final double radius; final double fontSize; final String? text; const _AvatarCircle({ required this.radius, required this.fontSize, this.text, }); @override Widget build(BuildContext context) { final colorScheme = Theme.of(context).colorScheme; final isDark = Theme.of(context).brightness == Brightness.dark; return CircleAvatar( radius: radius, backgroundColor: colorScheme.primary.withOpacity(0.15), child: Text( text ?? '₿', style: TextStyle( fontSize: fontSize, color: colorScheme.primary, fontWeight: FontWeight.w700, ), ), ); } } // ============================================================ // Menu Group 1 - 福利中心 / 实名认证 / 安全设置 / 消息通知 // ============================================================ class _MenuGroup1 extends StatelessWidget { final int kycStatus; final void Function(String) onShowComingSoon; const _MenuGroup1({ required this.kycStatus, required this.onShowComingSoon, }); @override Widget build(BuildContext context) { final colorScheme = Theme.of(context).colorScheme; final isDark = Theme.of(context).brightness == Brightness.dark; return Container( width: double.infinity, clipBehavior: Clip.antiAlias, decoration: BoxDecoration( color: isDark ? colorScheme.surfaceContainer : colorScheme.surfaceContainerHigh, borderRadius: BorderRadius.circular(AppRadius.lg), border: Border.all( color: colorScheme.outlineVariant.withOpacity(0.15), ), ), child: Column( children: [ // 福利中心 _MenuRow( icon: LucideIcons.gift, iconColor: AppColorScheme.darkSecondary, // gold title: '福利中心', onTap: () { Navigator.push( context, MaterialPageRoute(builder: (_) => const WelfareCenterPage()), ); }, ), _MenuDivider(), // 实名认证 _MenuRow( icon: LucideIcons.shieldCheck, iconColor: AppColorScheme.getUpColor(isDark), title: '实名认证', trailing: _KycBadge(kycStatus: kycStatus), onTap: () { if (kycStatus == 2) { _showKycStatusDialog(context); } else { Navigator.push( context, MaterialPageRoute(builder: (_) => const KycPage()), ); } }, ), _MenuDivider(), // 安全设置 _MenuRow( icon: LucideIcons.lock, iconColor: colorScheme.onSurfaceVariant, title: '安全设置', onTap: () => onShowComingSoon('安全设置'), ), _MenuDivider(), // 消息通知 _MenuRow( icon: LucideIcons.bell, iconColor: colorScheme.onSurfaceVariant, title: '消息通知', trailing: _RedDotIndicator(), onTap: () => onShowComingSoon('消息通知'), ), ], ), ); } } // ============================================================ // Menu Group 2 - 深色模式 / 系统设置 / 关于我们 // ============================================================ class _MenuGroup2 extends StatelessWidget { final VoidCallback onShowAbout; const _MenuGroup2({required this.onShowAbout}); @override Widget build(BuildContext context) { final colorScheme = Theme.of(context).colorScheme; final isDark = Theme.of(context).brightness == Brightness.dark; return Container( width: double.infinity, clipBehavior: Clip.antiAlias, decoration: BoxDecoration( color: isDark ? colorScheme.surfaceContainer : colorScheme.surfaceContainerHigh, borderRadius: BorderRadius.circular(AppRadius.lg), border: Border.all( color: colorScheme.outlineVariant.withOpacity(0.15), ), ), child: Column( children: [ // 深色模式 _DarkModeRow(), _MenuDivider(), // 系统设置 _MenuRow( icon: LucideIcons.settings, iconColor: colorScheme.onSurfaceVariant, title: '系统设置', onTap: () { // TODO: 系统设置 }, ), _MenuDivider(), // 关于我们 _MenuRow( icon: LucideIcons.info, iconColor: colorScheme.onSurfaceVariant, title: '关于我们', onTap: onShowAbout, ), ], ), ); } } // ============================================================ // Shared menu row components // ============================================================ /// 单行菜单项:icon-in-box + title + trailing (chevron / badge / toggle) class _MenuRow extends StatelessWidget { final IconData icon; final Color iconColor; final String title; final Widget? trailing; final VoidCallback? onTap; const _MenuRow({ required this.icon, required this.iconColor, required this.title, this.trailing, this.onTap, }); @override Widget build(BuildContext context) { return InkWell( onTap: onTap, child: Padding( padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 14), child: Row( children: [ // Icon in 36x36 rounded container Container( width: 36, height: 36, decoration: BoxDecoration( color: Theme.of(context).brightness == Brightness.dark ? Theme.of(context).colorScheme.surfaceContainerHigh : Theme.of(context).colorScheme.surfaceContainerHighest, borderRadius: BorderRadius.circular(8), ), child: Center( child: Icon(icon, size: 18, color: iconColor), ), ), const SizedBox(width: 10), // Title Expanded( child: Text( title, style: GoogleFonts.inter( fontSize: 14, fontWeight: FontWeight.w500, color: Theme.of(context).colorScheme.onSurface, ), ), ), // Trailing if (trailing != null) trailing! else Icon( LucideIcons.chevronRight, size: 16, color: Theme.of(context).colorScheme.onSurfaceVariant, ), ], ), ), ); } } /// Menu group divider class _MenuDivider extends StatelessWidget { @override Widget build(BuildContext context) { return Container( height: 1, color: Theme.of(context).colorScheme.outlineVariant.withOpacity(0.15), margin: const EdgeInsets.only(left: 62), ); } } // ============================================================ // Special trailing widgets // ============================================================ /// KYC status badge (e.g. "已认证" green badge + chevron) class _KycBadge extends StatelessWidget { final int kycStatus; const _KycBadge({required this.kycStatus}); @override Widget build(BuildContext context) { final isDark = Theme.of(context).brightness == Brightness.dark; final green = AppColorScheme.getUpColor(isDark); if (kycStatus == 2) { return Row( mainAxisSize: MainAxisSize.min, children: [ Container( padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 3), decoration: BoxDecoration( color: green.withOpacity(0.1), borderRadius: BorderRadius.circular(AppRadius.sm), ), child: Text( '已认证', style: GoogleFonts.inter( fontSize: 10, fontWeight: FontWeight.w500, color: green, ), ), ), const SizedBox(width: 8), Icon( LucideIcons.chevronRight, size: 16, color: Theme.of(context).colorScheme.onSurfaceVariant, ), ], ); } if (kycStatus == 1) { return Row( mainAxisSize: MainAxisSize.min, children: [ Container( padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 3), decoration: BoxDecoration( color: AppColorScheme.warning.withOpacity(0.1), borderRadius: BorderRadius.circular(AppRadius.sm), ), child: Text( '审核中', style: GoogleFonts.inter( fontSize: 10, fontWeight: FontWeight.w500, color: AppColorScheme.warning, ), ), ), const SizedBox(width: 8), Icon( LucideIcons.chevronRight, size: 16, color: Theme.of(context).colorScheme.onSurfaceVariant, ), ], ); } return Icon( LucideIcons.chevronRight, size: 16, color: Theme.of(context).colorScheme.onSurfaceVariant, ); } } /// Red dot indicator for notifications + chevron class _RedDotIndicator extends StatelessWidget { @override Widget build(BuildContext context) { return Row( mainAxisSize: MainAxisSize.min, children: [ Container( width: 8, height: 8, decoration: BoxDecoration( color: AppColorScheme.down, shape: BoxShape.circle, ), ), const SizedBox(width: 8), Icon( LucideIcons.chevronRight, size: 16, color: Theme.of(context).colorScheme.onSurfaceVariant, ), ], ); } } /// Dark mode toggle row class _DarkModeRow extends StatelessWidget { @override Widget build(BuildContext context) { final colorScheme = Theme.of(context).colorScheme; final isDark = Theme.of(context).brightness == Brightness.dark; final themeProvider = context.watch(); return Padding( padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 14), child: Row( children: [ // Icon in 36x36 rounded container Container( width: 36, height: 36, decoration: BoxDecoration( color: isDark ? colorScheme.surfaceContainerHigh : colorScheme.surfaceContainerHighest, borderRadius: BorderRadius.circular(8), ), child: Center( child: Icon( LucideIcons.moon, size: 18, color: colorScheme.onSurfaceVariant, ), ), ), const SizedBox(width: 10), Expanded( child: Text( '深色模式', style: GoogleFonts.inter( fontSize: 14, fontWeight: FontWeight.w500, color: colorScheme.onSurface, ), ), ), // Toggle switch - matching .pen design (44x24 rounded pill) GestureDetector( onTap: () => themeProvider.toggleTheme(), child: AnimatedContainer( duration: const Duration(milliseconds: 200), width: 44, height: 24, padding: const EdgeInsets.all(2), decoration: BoxDecoration( color: isDark ? colorScheme.surfaceContainerHigh : colorScheme.surfaceContainerHighest, borderRadius: BorderRadius.circular(12), ), child: AnimatedAlign( duration: const Duration(milliseconds: 200), alignment: themeProvider.isDarkMode ? Alignment.centerRight : Alignment.centerLeft, child: Container( width: 20, height: 20, decoration: BoxDecoration( color: colorScheme.onSurface, shape: BoxShape.circle, ), ), ), ), ), ], ), ); } } // ============================================================ // Logout button // ============================================================ class _LogoutButton extends StatelessWidget { final VoidCallback onLogout; const _LogoutButton({required this.onLogout}); @override Widget build(BuildContext context) { final colorScheme = Theme.of(context).colorScheme; return GestureDetector( onTap: onLogout, child: Container( width: double.infinity, height: 48, decoration: BoxDecoration( color: AppColorScheme.down.withOpacity(0.05), borderRadius: BorderRadius.circular(AppRadius.lg), border: Border.all( color: AppColorScheme.down.withOpacity(0.15), ), ), child: Center( child: Text( '退出登录', style: GoogleFonts.inter( fontSize: 14, fontWeight: FontWeight.w600, color: AppColorScheme.down, ), ), ), ), ); } } // ============================================================ // Info row (used in about dialog) // ============================================================ class _InfoRow extends StatelessWidget { final IconData icon; final String text; const _InfoRow({required this.icon, required this.text}); @override Widget build(BuildContext context) { final colorScheme = Theme.of(context).colorScheme; return Row( children: [ Icon(icon, size: 14, color: colorScheme.onSurfaceVariant), SizedBox(width: AppSpacing.sm), Text( text, style: TextStyle( fontSize: 12, color: colorScheme.onSurfaceVariant, ), ), ], ); } } // ============================================================ // KYC status dialog // ============================================================ void _showKycStatusDialog(BuildContext context) { showShadDialog( context: context, builder: (ctx) => ShadDialog.alert( title: Row( children: [ Icon(Icons.check_circle, color: AppColorScheme.up, size: 20), SizedBox(width: AppSpacing.sm), const Text('实名认证'), ], ), description: const Text('您的实名认证已通过'), actions: [ ShadButton( child: const Text('确定'), onPressed: () => Navigator.of(ctx).pop(), ), ], ), ); }