import 'package:flutter/material.dart'; import 'package:intl/intl.dart'; import 'package:qpay/screens/accounts/account_provider.dart'; import 'package:qpay/screens/accounts/models/account_model.dart'; import 'package:shared_preferences/shared_preferences.dart'; class AccountBalanceWidget extends StatefulWidget { const AccountBalanceWidget({super.key}); @override State createState() => _AccountBalanceWidgetState(); } class _AccountBalanceWidgetState extends State with SingleTickerProviderStateMixin { late AccountProvider _accountProvider; AccountModel? _usdAccount; AccountModel? _zwgAccount; bool _isLoadingUsd = false; bool _isLoadingZwG = false; String? _usdError; String? _zwgError; String? _phoneNumber; late AnimationController _pulseController; @override void initState() { super.initState(); _pulseController = AnimationController( vsync: this, duration: const Duration(milliseconds: 800), ); _accountProvider = AccountProvider(); _loadBalances(); } @override void dispose() { _pulseController.dispose(); _accountProvider.dispose(); super.dispose(); } Future _loadBalances() async { final prefs = await SharedPreferences.getInstance(); _phoneNumber = prefs.getString('phone'); if (_phoneNumber == null || _phoneNumber!.isEmpty) return; setState(() { _isLoadingUsd = true; _isLoadingZwG = true; }); // Fetch USD balance final usdResult = await _accountProvider.fetchAccount( 'USD$_phoneNumber', ); if (mounted) { setState(() { _isLoadingUsd = false; if (usdResult.isSuccess && usdResult.data != null) { _usdAccount = usdResult.data; _usdError = null; } else { _usdError = usdResult.error; } }); } // Fetch ZWG balance final zwgResult = await _accountProvider.fetchAccount( 'ZWG$_phoneNumber', ); if (mounted) { setState(() { _isLoadingZwG = false; if (zwgResult.isSuccess && zwgResult.data != null) { _zwgAccount = zwgResult.data; _zwgError = null; } else { _zwgError = zwgResult.error; } }); } if (mounted) { _pulseController.forward(); } } @override Widget build(BuildContext context) { final theme = Theme.of(context); final isDark = theme.brightness == Brightness.dark; if (_phoneNumber == null || _phoneNumber!.isEmpty) { return const SizedBox.shrink(); } return Padding( padding: const EdgeInsets.only(bottom: 16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ _buildSectionLabel( theme, isDark, Icons.account_balance_wallet_rounded, 'Account Balances', ), const SizedBox(height: 12), Row( children: [ Expanded( child: _buildBalanceCard( theme: theme, isDark: isDark, currencyCode: 'USD', currencyName: 'US Dollar', flagAsset: 'united-states.png', balance: _usdAccount?.balance, isLoading: _isLoadingUsd, error: _usdError, gradientColors: [ const Color(0xFF0D47A1), const Color(0xFF1976D2), ], ), ), const SizedBox(width: 12), Expanded( child: _buildBalanceCard( theme: theme, isDark: isDark, currencyCode: 'ZWG', currencyName: 'Zimbabwe Gold', flagAsset: 'zimbabwe.png', balance: _zwgAccount?.balance, isLoading: _isLoadingZwG, error: _zwgError, gradientColors: [ const Color(0xFF1B5E20), const Color(0xFF388E3C), ], ), ), ], ), const SizedBox(height: 8), Center( child: TextButton.icon( onPressed: _isLoadingUsd || _isLoadingZwG ? null : () { _pulseController.reset(); _loadBalances(); }, icon: AnimatedBuilder( animation: _pulseController, builder: (context, child) { return Transform.rotate( angle: _pulseController.value * 6.2832, child: Icon( Icons.refresh_rounded, size: 16, color: _isLoadingUsd || _isLoadingZwG ? (isDark ? Colors.white24 : Colors.grey.shade400) : theme.colorScheme.primary, ), ); }, ), label: Text( _isLoadingUsd || _isLoadingZwG ? 'Refreshing...' : 'Refresh Balances', style: TextStyle( fontSize: 12, fontWeight: FontWeight.w600, color: _isLoadingUsd || _isLoadingZwG ? (isDark ? Colors.white24 : Colors.grey.shade400) : theme.colorScheme.primary, ), ), ), ), ], ), ); } Widget _buildBalanceCard({ required ThemeData theme, required bool isDark, required String currencyCode, required String currencyName, required String flagAsset, double? balance, required bool isLoading, String? error, required List gradientColors, }) { return Container( padding: const EdgeInsets.all(16), decoration: BoxDecoration( borderRadius: BorderRadius.circular(20), gradient: LinearGradient( colors: gradientColors, begin: Alignment.topLeft, end: Alignment.bottomRight, ), boxShadow: [ BoxShadow( color: gradientColors[0].withValues(alpha: 0.3), blurRadius: 12, offset: const Offset(0, 4), ), ], ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // Top row: flag + currency code Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Row( mainAxisSize: MainAxisSize.min, children: [ Container( width: 24, height: 24, decoration: BoxDecoration( shape: BoxShape.circle, border: Border.all( color: Colors.white.withValues(alpha: 0.3), width: 1.5, ), ), child: ClipOval( child: Image.asset( flagAsset, fit: BoxFit.cover, errorBuilder: (_, __, ___) => Icon( Icons.monetization_on_outlined, size: 14, color: Colors.white.withValues(alpha: 0.8), ), ), ), ), const SizedBox(width: 8), Text( currencyCode, style: const TextStyle( fontSize: 13, fontWeight: FontWeight.w700, color: Colors.white, letterSpacing: 0.5, ), ), ], ), Container( padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 2), decoration: BoxDecoration( color: Colors.white.withValues(alpha: 0.2), borderRadius: BorderRadius.circular(8), ), child: Text( currencyName, style: TextStyle( fontSize: 8, fontWeight: FontWeight.w500, color: Colors.white.withValues(alpha: 0.9), ), ), ), ], ), const SizedBox(height: 16), // Balance amount if (isLoading) Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Container( width: 80, height: 14, decoration: BoxDecoration( color: Colors.white.withValues(alpha: 0.3), borderRadius: BorderRadius.circular(4), ), ), const SizedBox(height: 4), Container( width: 50, height: 10, decoration: BoxDecoration( color: Colors.white.withValues(alpha: 0.2), borderRadius: BorderRadius.circular(4), ), ), ], ) else if (error != null) Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Icon( Icons.error_outline_rounded, color: Colors.white.withValues(alpha: 0.7), size: 20, ), const SizedBox(height: 4), Text( 'Unavailable', style: TextStyle( fontSize: 11, fontWeight: FontWeight.w500, color: Colors.white.withValues(alpha: 0.7), ), ), ], ) else ...[ Text( _formatBalance(balance ?? 0.0), style: const TextStyle( fontSize: 22, fontWeight: FontWeight.w800, color: Colors.white, letterSpacing: 0.5, height: 1.1, ), ), const SizedBox(height: 4), Text( currencyCode == 'USD' ? 'Available Balance' : 'Available Balance', style: TextStyle( fontSize: 10, fontWeight: FontWeight.w400, color: Colors.white.withValues(alpha: 0.7), ), ), ], ], ), ); } Widget _buildSectionLabel( ThemeData theme, bool isDark, IconData icon, String label, ) { return Row( children: [ Container( width: 32, height: 32, decoration: BoxDecoration( color: theme.colorScheme.primary.withValues(alpha: 0.1), borderRadius: BorderRadius.circular(10), ), child: Icon(icon, size: 16, color: theme.colorScheme.primary), ), const SizedBox(width: 10), Text( label, style: TextStyle( fontSize: 16, fontWeight: FontWeight.w700, color: isDark ? Colors.white : Colors.black87, letterSpacing: 0.3, ), ), ], ); } String _formatBalance(double balance) { final formatter = NumberFormat('#,##0.00', 'en_US'); return '\$${formatter.format(balance)}'; } }