import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:lucide_icons_flutter/lucide_icons.dart'; import 'package:provider/provider.dart'; import 'package:shadcn_ui/shadcn_ui.dart'; import '../../../core/theme/app_color_scheme.dart'; import '../../../core/theme/app_spacing.dart'; import '../../../core/theme/app_theme.dart'; import '../../../core/theme/app_theme_extension.dart'; import '../../../core/utils/toast_utils.dart'; import '../../../providers/asset_provider.dart'; /// 充值頁面 — 獨立頁面,替代彈窗 class DepositPage extends StatefulWidget { const DepositPage({super.key}); @override State createState() => _DepositPageState(); } class _DepositPageState extends State { final _amountController = TextEditingController(); final _formKey = GlobalKey(); bool _isSubmitting = false; // 充值結果狀態 bool _showResult = false; String? _orderNo; String? _amount; String? _walletAddress; String _walletNetwork = 'TRC20'; @override void dispose() { _amountController.dispose(); super.dispose(); } Future _submitDeposit() async { if (!_formKey.currentState!.saveAndValidate()) return; if (_isSubmitting) return; setState(() => _isSubmitting = true); try { final response = await context.read().deposit( amount: _amountController.text, ); if (!mounted) return; if (response.success && response.data != null) { setState(() { _showResult = true; _orderNo = response.data!['orderNo'] as String? ?? ''; _amount = response.data!['amount']?.toString() ?? '0.00'; _walletAddress = response.data!['walletAddress'] as String? ?? ''; _walletNetwork = response.data!['walletNetwork'] as String? ?? 'TRC20'; }); } else { ToastUtils.showError(response.message ?? '申請失敗'); } } catch (e) { if (mounted) ToastUtils.showError('申請失敗: $e'); } finally { if (mounted) setState(() => _isSubmitting = false); } } Future _confirmPay() async { if (_orderNo == null) return; final confirmed = await showDialog( context: context, builder: (ctx) => AlertDialog( title: const Text('確認已打款'), content: const Text('確認您已完成向指定地址的轉賬?'), actions: [ TextButton( onPressed: () => Navigator.pop(ctx, false), child: const Text('取消'), ), TextButton( onPressed: () => Navigator.pop(ctx, true), child: const Text('確認'), ), ], ), ); if (confirmed != true || !mounted) return; try { final response = await context.read().confirmPay(_orderNo!); if (!mounted) return; if (response.success) { ToastUtils.showSuccess('確認成功,請等待管理員審核'); Navigator.of(context).pop(true); } else { ToastUtils.showError(response.message ?? '確認失敗'); } } catch (e) { if (mounted) ToastUtils.showError('確認失敗: $e'); } } // ============================================ // 構建 UI // ============================================ @override Widget build(BuildContext context) { final colorScheme = context.colors; return Scaffold( backgroundColor: colorScheme.background, appBar: AppBar( leading: IconButton( icon: const Icon(LucideIcons.arrowLeft, size: 20), onPressed: () => Navigator.of(context).pop(), ), title: Text( '充值', style: AppTextStyles.headlineLarge(context).copyWith( color: colorScheme.onSurface, ), ), backgroundColor: colorScheme.background, elevation: 0, scrolledUnderElevation: 0, centerTitle: true, ), body: _showResult ? _buildResultView() : _buildFormView(), ); } /// 表單視圖 — 輸入充值金額 Widget _buildFormView() { final colorScheme = context.colors; return SingleChildScrollView( padding: const EdgeInsets.all(AppSpacing.lg), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // 幣種選擇卡片 Container( width: double.infinity, padding: const EdgeInsets.all(AppSpacing.md), decoration: BoxDecoration( color: colorScheme.surfaceContainer, borderRadius: BorderRadius.circular(AppRadius.lg), border: Border.all( color: colorScheme.outlineVariant.withValues(alpha: 0.3), ), ), child: Row( children: [ Container( width: 40, height: 40, decoration: BoxDecoration( color: colorScheme.primary.withValues(alpha: 0.1), borderRadius: BorderRadius.circular(AppRadius.md), ), child: Icon( LucideIcons.coins, color: colorScheme.primary, size: 20, ), ), const SizedBox(width: AppSpacing.md), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( 'USDT', style: AppTextStyles.headlineMedium(context).copyWith( fontWeight: FontWeight.bold, ), ), Text( 'Tether USD', style: AppTextStyles.bodySmall(context).copyWith( color: colorScheme.onSurfaceVariant, ), ), ], ), ), ], ), ), const SizedBox(height: AppSpacing.xl), // 金額輸入 Text( '充值金額', style: AppTextStyles.bodyLarge(context).copyWith( fontWeight: FontWeight.w600, ), ), const SizedBox(height: AppSpacing.sm), ShadForm( key: _formKey, child: ShadInputFormField( id: 'amount', controller: _amountController, placeholder: const Text('請輸入充值金額'), keyboardType: const TextInputType.numberWithOptions(decimal: true), validator: (v) { if (v == null || v.isEmpty) return '請輸入金額'; final n = double.tryParse(v); if (n == null || n <= 0) return '請輸入有效金額'; if (n < 1000) return '單筆最低充值 1000 USDT'; return null; }, ), ), const SizedBox(height: AppSpacing.sm), // 最低金額提示 Container( padding: const EdgeInsets.symmetric( horizontal: AppSpacing.md, vertical: AppSpacing.sm, ), decoration: BoxDecoration( color: AppColorScheme.info.withValues(alpha: 0.08), borderRadius: BorderRadius.circular(AppRadius.md), border: Border.all( color: AppColorScheme.info.withValues(alpha: 0.15), ), ), child: Row( children: [ Icon(Icons.info_outline, size: 16, color: AppColorScheme.info), const SizedBox(width: AppSpacing.sm), Text( '單筆最低充值 1000 USDT', style: AppTextStyles.bodySmall(context).copyWith( color: AppColorScheme.info, ), ), ], ), ), const SizedBox(height: AppSpacing.xl), // 操作說明 Text( '操作流程', style: AppTextStyles.bodyLarge(context).copyWith( fontWeight: FontWeight.w600, ), ), const SizedBox(height: AppSpacing.md), _buildStepItem(1, '輸入充值金額並提交申請'), _buildStepItem(2, '向指定錢包地址轉賬'), _buildStepItem(3, '點擊「已打款」確認'), _buildStepItem(4, '等待管理員審核通過'), const SizedBox(height: AppSpacing.xxl), // 提交按鈕 SizedBox( width: double.infinity, height: 50, child: ElevatedButton( onPressed: _isSubmitting ? null : _submitDeposit, style: ElevatedButton.styleFrom( backgroundColor: colorScheme.primary, foregroundColor: colorScheme.onPrimary, disabledBackgroundColor: colorScheme.primary.withValues(alpha: 0.5), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(AppRadius.lg), ), elevation: 0, ), child: _isSubmitting ? const SizedBox( width: 20, height: 20, child: CircularProgressIndicator( strokeWidth: 2, color: Colors.white, ), ) : Text( '下一步', style: AppTextStyles.headlineMedium(context).copyWith( fontWeight: FontWeight.w600, color: colorScheme.onPrimary, ), ), ), ), const SizedBox(height: AppSpacing.lg), // 安全提示 _buildSecurityTip(), ], ), ); } /// 結果視圖 — 展示錢包地址和確認打款 Widget _buildResultView() { final colorScheme = context.colors; return SingleChildScrollView( padding: const EdgeInsets.all(AppSpacing.lg), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // 成功提示 Center( child: Column( children: [ Container( width: 56, height: 56, decoration: BoxDecoration( color: context.appColors.up.withValues(alpha: 0.12), shape: BoxShape.circle, ), child: Icon( Icons.check_circle_outline_rounded, color: context.appColors.up, size: 32, ), ), const SizedBox(height: AppSpacing.md), Text( '充值申請成功', style: AppTextStyles.headlineLarge(context).copyWith( fontWeight: FontWeight.w700, ), ), const SizedBox(height: AppSpacing.xs), Text( '請向以下地址轉賬完成充值', style: AppTextStyles.bodyMedium(context).copyWith( color: colorScheme.onSurfaceVariant, ), ), ], ), ), const SizedBox(height: AppSpacing.xl), // 訂單信息 Container( width: double.infinity, padding: const EdgeInsets.all(AppSpacing.md), decoration: BoxDecoration( color: colorScheme.surfaceContainer, borderRadius: BorderRadius.circular(AppRadius.lg), border: Border.all( color: colorScheme.outlineVariant.withValues(alpha: 0.3), ), ), child: Column( children: [ _buildInfoRow('訂單號', _orderNo ?? ''), const SizedBox(height: AppSpacing.sm), Divider(color: colorScheme.outlineVariant.withValues(alpha: 0.2), height: 1), const SizedBox(height: AppSpacing.sm), _buildInfoRow('充值金額', '${_amount ?? "0.00"} USDT', isBold: true), ], ), ), const SizedBox(height: AppSpacing.lg), // 錢包地址 Text( '收款地址', style: AppTextStyles.bodyLarge(context).copyWith( fontWeight: FontWeight.w600, ), ), const SizedBox(height: AppSpacing.sm), Container( width: double.infinity, padding: const EdgeInsets.all(AppSpacing.md), decoration: BoxDecoration( color: colorScheme.surfaceContainer, borderRadius: BorderRadius.circular(AppRadius.lg), border: Border.all( color: colorScheme.outlineVariant.withValues(alpha: 0.3), ), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Expanded( child: Text( _walletAddress ?? '', style: AppTextStyles.bodyMedium(context).copyWith( fontFamily: 'monospace', ), ), ), GestureDetector( onTap: () { Clipboard.setData(ClipboardData(text: _walletAddress ?? '')); ToastUtils.showSuccess('地址已複製到剪貼板'); }, child: Container( padding: const EdgeInsets.all(AppSpacing.sm), decoration: BoxDecoration( color: colorScheme.primary.withValues(alpha: 0.1), borderRadius: BorderRadius.circular(AppRadius.sm), ), child: Icon( LucideIcons.copy, size: 16, color: colorScheme.primary, ), ), ), ], ), const SizedBox(height: AppSpacing.sm), Text( '網絡: $_walletNetwork', style: AppTextStyles.bodySmall(context).copyWith( color: colorScheme.onSurfaceVariant, ), ), ], ), ), const SizedBox(height: AppSpacing.md), // 重要提示 Container( width: double.infinity, padding: const EdgeInsets.all(AppSpacing.md), decoration: BoxDecoration( color: AppColorScheme.warning.withValues(alpha: 0.08), borderRadius: BorderRadius.circular(AppRadius.md), border: Border.all( color: AppColorScheme.warning.withValues(alpha: 0.15), ), ), child: Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ Icon(Icons.info_outline, size: 18, color: AppColorScheme.warning), const SizedBox(width: AppSpacing.sm), Expanded( child: Text( '轉賬完成後請點擊下方「已打款」按鈕確認,管理員審核通過後資金將到賬。', style: AppTextStyles.bodyMedium(context).copyWith( color: AppColorScheme.warning, ), ), ), ], ), ), const SizedBox(height: AppSpacing.xl), // 操作按鈕 Row( children: [ Expanded( child: SizedBox( height: 50, child: OutlinedButton( onPressed: () => Navigator.of(context).pop(), style: OutlinedButton.styleFrom( side: BorderSide(color: colorScheme.outline), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(AppRadius.lg), ), ), child: Text( '稍後確認', style: AppTextStyles.headlineSmall(context).copyWith( fontWeight: FontWeight.w600, ), ), ), ), ), const SizedBox(width: AppSpacing.md), Expanded( child: SizedBox( height: 50, child: ElevatedButton( onPressed: _confirmPay, style: ElevatedButton.styleFrom( backgroundColor: colorScheme.primary, foregroundColor: colorScheme.onPrimary, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(AppRadius.lg), ), elevation: 0, ), child: Text( '已打款', style: AppTextStyles.headlineSmall(context).copyWith( fontWeight: FontWeight.w600, color: colorScheme.onPrimary, ), ), ), ), ), ], ), const SizedBox(height: AppSpacing.lg), _buildSecurityTip(), ], ), ); } // ============================================ // 輔助組件 // ============================================ Widget _buildStepItem(int step, String text) { final colorScheme = context.colors; return Padding( padding: const EdgeInsets.only(bottom: AppSpacing.sm + AppSpacing.xs), child: Row( children: [ Container( width: 24, height: 24, decoration: BoxDecoration( color: colorScheme.primary.withValues(alpha: 0.1), borderRadius: BorderRadius.circular(AppRadius.sm), ), child: Center( child: Text( '$step', style: AppTextStyles.labelSmall(context).copyWith( color: colorScheme.primary, fontWeight: FontWeight.bold, ), ), ), ), const SizedBox(width: AppSpacing.sm), Expanded( child: Text( text, style: AppTextStyles.bodyMedium(context).copyWith( color: colorScheme.onSurfaceVariant, ), ), ), ], ), ); } Widget _buildInfoRow(String label, String value, {bool isBold = false}) { final colorScheme = context.colors; return Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( label, style: AppTextStyles.bodyMedium(context).copyWith( color: colorScheme.onSurfaceVariant, ), ), Flexible( child: Text( value, style: AppTextStyles.bodyMedium(context).copyWith( fontWeight: isBold ? FontWeight.bold : FontWeight.w400, ), textAlign: TextAlign.right, ), ), ], ); } Widget _buildSecurityTip() { final colorScheme = context.colors; return Container( width: double.infinity, padding: const EdgeInsets.all(AppSpacing.md), decoration: BoxDecoration( color: colorScheme.surfaceContainer, borderRadius: BorderRadius.circular(AppRadius.md), ), child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon( Icons.verified_user_outlined, size: 14, color: colorScheme.onSurfaceVariant.withValues(alpha: 0.5), ), const SizedBox(width: AppSpacing.xs), Text( '資金安全由平台全程保障', style: AppTextStyles.bodySmall(context).copyWith( color: colorScheme.onSurfaceVariant.withValues(alpha: 0.5), ), ), ], ), ); } }