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'; import '../../../components/coin_icon.dart'; import '../../chart/chart_page.dart'; /// 持倉區域 /// Header: "我的資產" + "查看全部 >" /// 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 InkWell( onTap: () { Navigator.push( context, MaterialPageRoute(builder: (_) => ChartPage(symbol: coinCode)), ); }, child: 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, child: CoinIcon( symbol: coinCode, size: 36, isCircle: false, ), ), 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, ), ), ], ), ], ), ), ); } }