import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import '../../../../core/theme/app_theme.dart'; import '../../../../core/widgets/glass_container.dart'; import '../../../../core/widgets/shimmer_loading.dart'; import '../../bloc/fundamentals/asset_fundamentals_bloc.dart'; import '../../bloc/fundamentals/asset_fundamentals_event.dart'; import '../../bloc/fundamentals/asset_fundamentals_state.dart'; import '../../widgets/fundamentals/analyst_price_target_card.dart'; import '../../widgets/fundamentals/fundamental_category_panels.dart'; import '../../widgets/fundamentals/company_profile_section.dart'; class FundamentalsTab extends StatelessWidget { final String isin; final String? symbol; final bool isEmbedded; const FundamentalsTab({ super.key, this.symbol, this.isEmbedded = false, required this.isin, }); String _getCurrencySymbol(String? ticker) { if (ticker == null || ticker.isEmpty) return '€'; final t = ticker.toUpperCase(); if (t.endsWith('.DE') || t.endsWith('.F') || t.endsWith('.VI') || t.endsWith('.PA') || t.endsWith('.AS') || t.endsWith('.MC') || t.endsWith('.MI')) { return '€'; } if (t.endsWith('.L')) return '£'; if (t.endsWith('.TO') || t.endsWith('.V')) return 'CA\$'; return '\$'; } String _getCurrencyCode(String? ticker) { if (ticker == null || ticker.isEmpty) return 'EUR'; final t = ticker.toUpperCase(); if (t.endsWith('.DE') || t.endsWith('.F') || t.endsWith('.VI') || t.endsWith('.PA') || t.endsWith('.AS') || t.endsWith('.MC') || t.endsWith('.MI')) { return 'EUR'; } if (t.endsWith('.L')) return 'GBP'; if (t.endsWith('.TO') || t.endsWith('.V')) return 'CAD'; return 'USD'; } @override Widget build(BuildContext context) { return BlocBuilder( builder: (context, state) { if (state is AssetFundamentalsLoading) { return _buildFundamentalsShimmer(context); } if (state is AssetFundamentalsError) { return Center( child: GlassContainer( padding: const EdgeInsets.all(24), child: Column( mainAxisSize: MainAxisSize.min, children: [ Icon(Icons.error_outline, color: AppTheme.accentRed, size: 48), const SizedBox(height: 12), Text('Fehler beim Laden der Fundamentaldaten: ${state.message}', style: const TextStyle(color: Colors.white70)), const SizedBox(height: 16), ElevatedButton.icon( onPressed: () => context.read().add(LoadAssetFundamentals(isin, ticker: symbol, forceRefresh: true)), icon: const Icon(Icons.refresh), label: const Text('Erneut versuchen'), ), ], ), ), ); } if (state is AssetFundamentalsLoaded && state.data != null) { final data = state.data!; final sym = _getCurrencySymbol(data.ticker); final curCode = _getCurrencyCode(data.ticker); return SingleChildScrollView( physics: isEmbedded ? const NeverScrollableScrollPhysics() : null, padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // 1. Analyst Forecasts & Price Targets Header Card AnalystPriceTargetCard(data: data, currencySymbol: sym), const SizedBox(height: 20), // 2. Responsive Side-by-Side Category List Panels (Valuation, Profitability, Dividends) FundamentalCategoryPanels(data: data, currencySymbol: sym, currencyCode: curCode), const SizedBox(height: 20), // 3. Company Description & Detailed Executive Board _buildSectionHeader('Unternehmensprofil & Führungskräfte', Icons.business_outlined), const SizedBox(height: 12), CompanyProfileSection(data: data, currencySymbol: sym), ], ), ); } return _buildEmptyState(context); }, ); } Widget _buildSectionHeader(String title, IconData icon) { return Row( children: [ Icon(icon, color: AppTheme.primaryEmerald, size: 20), const SizedBox(width: 8), Text(title, style: const TextStyle(fontSize: 16, fontWeight: FontWeight.bold, color: Colors.white)), ], ); } Widget _buildEmptyState(BuildContext context) { return Center( child: GlassContainer( padding: const EdgeInsets.all(24), child: Column( mainAxisSize: MainAxisSize.min, children: [ Icon(Icons.analytics_outlined, color: AppTheme.textMuted, size: 48), const SizedBox(height: 12), const Text('Keine Fundamentaldaten verfügbar.', style: TextStyle(color: Colors.white70)), const SizedBox(height: 16), ElevatedButton.icon( onPressed: () => context.read().add(LoadAssetFundamentals(isin, ticker: symbol, forceRefresh: true)), icon: const Icon(Icons.refresh), label: const Text('Aktualisieren'), ), ], ), ), ); } Widget _buildFundamentalsShimmer(BuildContext context) { final isDesktop = MediaQuery.of(context).size.width >= 1050; final isTablet = MediaQuery.of(context).size.width >= 680 && MediaQuery.of(context).size.width < 1050; Widget panelShimmer() { return GlassContainer( padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 14), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const ShimmerLoading(width: 180, height: 18, borderRadius: 6), const SizedBox(height: 12), const Divider(color: Colors.white10, height: 1), const SizedBox(height: 8), for (int i = 0; i < 9; i++) ...[ Padding( padding: const EdgeInsets.symmetric(vertical: 6, horizontal: 4), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: const [ ShimmerLoading(width: 100, height: 14, borderRadius: 4), ShimmerLoading(width: 60, height: 14, borderRadius: 4), ], ), ), ], ], ), ); } return SingleChildScrollView( physics: isEmbedded ? const NeverScrollableScrollPhysics() : null, padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const ShimmerLoading(width: double.infinity, height: 86, borderRadius: 16), const SizedBox(height: 20), if (isDesktop) Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ Expanded(child: panelShimmer()), const SizedBox(width: 14), Expanded(child: panelShimmer()), const SizedBox(width: 14), Expanded(child: panelShimmer()), ], ) else if (isTablet) Column( children: [ Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ Expanded(child: panelShimmer()), const SizedBox(width: 12), Expanded(child: panelShimmer()), ], ), const SizedBox(height: 12), panelShimmer(), ], ) else Column( children: [ panelShimmer(), const SizedBox(height: 12), panelShimmer(), const SizedBox(height: 12), panelShimmer(), ], ), const SizedBox(height: 20), const ShimmerLoading(width: 220, height: 20, borderRadius: 6), const SizedBox(height: 12), const ShimmerLoading(width: double.infinity, height: 140, borderRadius: 16), ], ), ); } }