import 'package:flutter/material.dart'; import '../../../../core/theme/app_theme.dart'; import '../../../../core/theme/app_theme_extension.dart'; import '../../../../core/theme/app_spacing.dart'; import '../../../../data/models/account_models.dart'; import '../../../components/glass_panel.dart'; /// 持仓区域 — .pen nodes th9BG (header) + 6X6tC (card) /// Holdings Header: "交易账户持仓" 16px w600 $text-primary | "查看全部 >" 12px normal $text-secondary /// Holdings Card: cornerRadius lg, fill $surface-card, stroke $border-default 1px class HoldingsSection extends StatelessWidget { final List holdings; const HoldingsSection({super.key, required this.holdings}); @override Widget build(BuildContext context) { final colorScheme = Theme.of(context).colorScheme; return Column( children: [ // Header row: "交易账户持仓" + "查看全部 >" Padding( padding: const EdgeInsets.only(bottom: AppSpacing.sm), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( '交易账户持仓', style: AppTextStyles.headlineLarge(context), ), Text( '查看全部 >', style: AppTextStyles.bodyMedium(context).copyWith( color: colorScheme.onSurfaceVariant, fontWeight: FontWeight.w400, ), ), ], ), ), // Holdings card — uses real provider.holdings data if (holdings.isEmpty) Padding( padding: const EdgeInsets.all(AppSpacing.xl), child: Text( '暂无持仓', style: AppTextStyles.bodyLarge(context).copyWith( color: colorScheme.onSurfaceVariant, ), ), ) else GlassPanel( padding: EdgeInsets.zero, borderRadius: BorderRadius.circular(AppRadius.lg), child: Column( children: List.generate(holdings.length, (index) { final h = holdings[index] as AccountTrade; final isProfit = h.profitRate >= 0; return Column( children: [ HoldingRow( coinCode: h.coinCode, quantity: double.tryParse(h.quantity)?.toStringAsFixed(4) ?? h.quantity, value: '${double.tryParse(h.currentValue)?.toStringAsFixed(2) ?? h.currentValue} USDT', profitRate: '${isProfit ? '+' : ''}${h.profitRate.toStringAsFixed(2)}%', isProfit: isProfit, ), if (index < holdings.length - 1) const HoldingDivider(), ], ); }), ), ), ], ); } } /// 持仓行分隔线 — .pen node BCCbR / yejhE /// fill: $border-default, height: 1, opacity: 0.5 class HoldingDivider extends StatelessWidget { const HoldingDivider({super.key}); @override Widget build(BuildContext context) { final colorScheme = Theme.of(context).colorScheme; return Container( height: 1, margin: const EdgeInsets.symmetric(horizontal: AppSpacing.md), color: colorScheme.outlineVariant.withValues(alpha: 0.5), ); } } /// 持仓行 — matching .pen nodes dAt4j / eK6vq / jiSUK /// padding [14, 16], space_between layout /// Left: avatar circle (36x36, radius 18, fill $accent-light) + coin info (gap 2) /// Right: value + pnl (gap 2, align end) class HoldingRow extends StatelessWidget { final String coinCode; final String quantity; final String value; final String profitRate; final bool isProfit; const HoldingRow({ super.key, required this.coinCode, required this.quantity, required this.value, required this.profitRate, required this.isProfit, }); @override Widget build(BuildContext context) { final accentColor = context.appColors.accentPrimary; final accentBgColor = accentColor.withValues(alpha: 0.1); final profitColor = isProfit ? context.appColors.up : context.appColors.down; return Padding( padding: const EdgeInsets.symmetric(horizontal: AppSpacing.md, vertical: 14), child: Row( children: [ // Avatar circle with first letter — .pen SJNDJ/EjSIN/3GQ5M Container( width: 36, height: 36, decoration: BoxDecoration( color: accentBgColor, borderRadius: BorderRadius.circular(18), ), alignment: Alignment.center, child: Text( coinCode.substring(0, 1), style: AppTextStyles.headlineMedium(context).copyWith( fontWeight: FontWeight.w700, color: accentColor, ), ), ), const SizedBox(width: 10), // Coin name + quantity — .pen fivxJ/Kxv3d/5CsoQ Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisSize: MainAxisSize.min, children: [ Text( coinCode, style: AppTextStyles.headlineMedium(context), ), const SizedBox(height: 2), Text( quantity, style: AppTextStyles.bodyMedium(context).copyWith( fontWeight: FontWeight.w400, color: context.colors.onSurfaceVariant, ), ), ], ), ), // Value + profit rate — .pen vYJsU/2nLAg/IlWck Column( crossAxisAlignment: CrossAxisAlignment.end, mainAxisSize: MainAxisSize.min, children: [ Text( value, style: AppTextStyles.numberMedium(context).copyWith( fontSize: 13, ), ), const SizedBox(height: 2), Text( profitRate, style: AppTextStyles.numberSmall(context).copyWith( color: profitColor, ), ), ], ), ], ), ); } }