import 'package:finlytic_app/features/favorites/cubit/favorites_cubit.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import '../../../core/network/api_client.dart'; import '../../../core/theme/app_theme.dart'; import '../../../core/utils/time_utils.dart'; import '../../../core/widgets/glass_container.dart'; import '../../asset_detail/views/asset_detail_screen.dart'; import '../models/news_article_model.dart'; import 'article_sentiment_dialog.dart'; /// News Card Item displaying news info, tagged assets, timestamp, and sentiment. class NewsCardItem extends StatelessWidget { final dynamic item; final ApiClient apiClient; const NewsCardItem({ super.key, required this.item, required this.apiClient, }); @override Widget build(BuildContext context) { final Map article = item is NewsArticleModel ? (item as NewsArticleModel).toJson() : (item is Map && item.containsKey('article') && item['article'] is Map ? Map.from(item['article']) : (item is Map ? Map.from(item) : {})); final Map? sentimentObj = (item is Map && item.containsKey('sentiment') && item['sentiment'] is Map) ? Map.from(item['sentiment']) : null; final title = article['title']?.toString() ?? article['Title']?.toString() ?? 'Nachrichtenartikel'; final summary = article['summary']?.toString() ?? article['Summary']?.toString() ?? article['contentRaw']?.toString() ?? ''; final author = article['author']?.toString() ?? article['Author']?.toString() ?? article['source']?.toString() ?? 'Finlytic News'; final rawPubTime = article['publishedAt']?.toString() ?? article['PublishedAt']?.toString() ?? article['scrapedAt']?.toString(); final formattedTime = TimeUtils.formatRelativeTime(rawPubTime); final pubTime = formattedTime.isNotEmpty ? formattedTime : 'Heute'; final rawStatus = article['status']?.toString() ?? article['Status']?.toString() ?? 'Completed'; final String? sentimentLabel = sentimentObj?['label']?.toString() ?? article['sentiment']?.toString(); final double? score = ((sentimentObj?['compoundScore'] ?? sentimentObj?['compound_score'] ?? article['sentimentScore']) as num?)?.toDouble(); final matchedAssetsRaw = article['MatchedAssets'] ?? article['matchedAssets']; final matchedAssets = matchedAssetsRaw is List ? matchedAssetsRaw : []; final favourites = context.read().state.favoriteDetails; return GlassContainer( margin: const EdgeInsets.only(bottom: 12), onTap: () { final NewsArticleModel articleModel; if (item is NewsArticleModel) { articleModel = item; } else if (item is Map) { articleModel = NewsArticleModel.fromJson(item); } else if (item is Map) { articleModel = NewsArticleModel.fromJson(Map.from(item)); } else { articleModel = NewsArticleModel( id: '', title: title, author: author, summary: summary, contentRaw: '', sourceUrl: '', scrapedAt: DateTime.now(), publishedAt: DateTime.now(), status: rawStatus, sentiment: sentimentLabel ?? 'NEUTRAL', sentimentScore: score ?? 0.0, confidence: 0.0, ); } showDialog( context: context, builder: (_) => ArticleSentimentDialog(articleData: articleModel), ); }, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ Expanded( child: Text(title, style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 15)), ), const SizedBox(width: 8), //badgeWidget, ], ), const SizedBox(height: 8), Text(summary, maxLines: 2, overflow: TextOverflow.ellipsis, style: TextStyle(color: AppTheme.textSecondary, fontSize: 13)), const SizedBox(height: 10), Text('$author • $pubTime', style: TextStyle(color: AppTheme.textMuted, fontSize: 11)), if (matchedAssets.isNotEmpty) ...[ const SizedBox(height: 8), Wrap( spacing: 4, runSpacing: 4, children: matchedAssets.map((assetItem) { final isin = assetItem['isin']!; final name = assetItem['name']!; final match = favourites.where((e) => e.isin == isin); final symbol = match.isEmpty ? null : match.first; return ActionChip( label: Text(name, style: TextStyle(fontSize: 10, color: AppTheme.accentCyan)), backgroundColor: AppTheme.glassSurface, padding: EdgeInsets.zero, materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, onPressed: () { Navigator.push( context, MaterialPageRoute( builder: (_) => AssetDetailScreen( isin: assetItem, name: name, symbol: symbol != null ? symbol.symbol : null, apiClient: apiClient, ), ), ); }, ); }).toList(), ), ], ], ), ); } }