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/technical/asset_technical_bloc.dart'; import '../../bloc/technical/asset_technical_event.dart'; import '../../bloc/technical/asset_technical_state.dart'; import '../../widgets/chart/candlestick_chart.dart'; import '../../widgets/technical/pattern_card_item.dart'; import '../../widgets/technical/signal_card_item.dart'; import '../../widgets/technical/indicator_ribbon_bar.dart'; import '../fullscreen_chart_screen.dart'; class TechnicalTab extends StatelessWidget { final String isin; final String? symbol; final bool isDesktopLeftPanel; final bool showChartOnly; final bool showDetailsOnly; final double chartHeight; const TechnicalTab({ super.key, this.symbol, this.isDesktopLeftPanel = false, this.showChartOnly = false, this.showDetailsOnly = false, this.chartHeight = 420, required this.isin, }); @override Widget build(BuildContext context) { return BlocBuilder( builder: (context, state) { if (state is AssetTechnicalLoading) { return _buildTechnicalShimmer(context); } if (state is AssetTechnicalError) { return Center( child: GlassContainer( padding: const EdgeInsets.all(24), child: Column( mainAxisSize: MainAxisSize.min, children: [ Icon(Icons.show_chart, color: AppTheme.accentRed, size: 48), const SizedBox(height: 12), Text( 'Fehler beim Laden der Technischen Analyse: ${state.message}', style: const TextStyle(color: Colors.white70), ), const SizedBox(height: 16), ElevatedButton.icon( onPressed: () => context.read().add( LoadAssetTechnical(isin, ticker: symbol, forceRefresh: true), ), icon: const Icon(Icons.refresh), label: const Text('Erneut versuchen'), ), ], ), ), ); } if (state is AssetTechnicalLoaded && state.data != null) { final data = state.data!; final candles = data.candles; final patterns = data.patterns; final signals = data.signals; final indicators = data.indicators; final activePatterns = []; for (int i = 0; i < patterns.length; i++) { if (!state.disabledPatternIndices.contains(i)) { activePatterns.add(patterns[i]); } } final chartWidget = CandlestickChart( candles: candles, indicators: indicators, patterns: activePatterns, signals: signals, showSma50: state.showSma50, showSma200: state.showSma200, showEma: state.showEma, showPatterns: state.showPatterns, showSignals: state.showSignals, showSupertrend: state.showSupertrend, height: chartHeight, onToggleFullscreen: () => FullscreenChartScreen.open(context, isin: isin, symbol: symbol), ); final chartRibbon = IndicatorRibbonBar( showSma50: state.showSma50, showSma200: state.showSma200, showEma: state.showEma, showSupertrend: state.showSupertrend, showPatterns: state.showPatterns, showSignals: state.showSignals, onToggleSma50: (v) => context.read().add(ToggleIndicatorFilter(showSma50: v)), onToggleSma200: (v) => context.read().add(ToggleIndicatorFilter(showSma200: v)), onToggleEma: (v) => context.read().add(ToggleIndicatorFilter(showEma: v)), onToggleSupertrend: (v) => context.read().add(ToggleIndicatorFilter(showSupertrend: v)), onTogglePatterns: (v) => context.read().add(ToggleIndicatorFilter(showPatterns: v)), onToggleSignals: (v) => context.read().add(ToggleIndicatorFilter(showSignals: v)), onToggleFullscreen: () => FullscreenChartScreen.open(context, isin: isin, symbol: symbol), ); if (showChartOnly) { return Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisSize: MainAxisSize.min, children: [ chartRibbon, const SizedBox(height: 10), chartWidget, ], ); } final detailsSection = Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ if (patterns.isNotEmpty) ...[ const Text('Erkannte Chartformationen & Muster', style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold, color: Colors.white)), const SizedBox(height: 8), for (int i = 0; i < patterns.length; i++) PatternCardItem( pattern: patterns[i], index: i, isEnabled: !state.disabledPatternIndices.contains(i), onToggle: (enabled) { context.read().add( TogglePatternFilter(patternIndex: i, enabled: enabled), ); }, ), const SizedBox(height: 16), ], if (signals.isNotEmpty) ...[ const Text('Strategische Kauf- & Verkaufssignale', style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold, color: Colors.white)), const SizedBox(height: 8), for (final sig in signals) SignalCardItem(signal: sig), ], ], ); if (showDetailsOnly) { return SingleChildScrollView( padding: const EdgeInsets.symmetric(vertical: 16), child: detailsSection, ); } return SingleChildScrollView( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ chartRibbon, const SizedBox(height: 8), chartWidget, const SizedBox(height: 16), detailsSection, const SizedBox(height: 16), ], ), ); } return Center( child: Text('Keine technisches Indikatoren verfügbar', style: TextStyle(color: AppTheme.textMuted)), ); }, ); } Widget _buildTechnicalShimmer(BuildContext context) { if (showChartOnly) { return Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisSize: MainAxisSize.min, children: [ const ShimmerLoading(width: double.infinity, height: 42, borderRadius: 12), const SizedBox(height: 8), ShimmerLoading(width: double.infinity, height: chartHeight, borderRadius: 16), ], ); } if (showDetailsOnly) { return SingleChildScrollView( padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const ShimmerLoading(width: 240, height: 20, borderRadius: 6), const SizedBox(height: 14), for (int i = 0; i < 4; i++) ...[ const ShimmerLoading(width: double.infinity, height: 68, borderRadius: 12), const SizedBox(height: 10), ], ], ), ); } return SingleChildScrollView( padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const ShimmerLoading(width: double.infinity, height: 42, borderRadius: 12), const SizedBox(height: 8), ShimmerLoading(width: double.infinity, height: chartHeight, borderRadius: 16), const SizedBox(height: 16), const ShimmerLoading(width: 240, height: 20, borderRadius: 6), const SizedBox(height: 14), for (int i = 0; i < 3; i++) ...[ const ShimmerLoading(width: double.infinity, height: 68, borderRadius: 12), const SizedBox(height: 10), ], ], ), ); } }