feat(asset_detail): modular fundamentals sections, executive salaries and logo resolution
This commit is contained in:
@@ -3,11 +3,11 @@ import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import '../../../../core/theme/app_theme.dart';
|
||||
import '../../../../core/widgets/asset_logo_widget.dart';
|
||||
import '../../../../shared/widgets/favorite_star_button.dart';
|
||||
import '../../bloc/header/asset_header_bloc.dart';
|
||||
import '../../bloc/header/asset_header_state.dart';
|
||||
import '../../bloc/fundamentals/asset_fundamentals_bloc.dart';
|
||||
import '../../bloc/fundamentals/asset_fundamentals_state.dart';
|
||||
import '../../bloc/technical/asset_technical_bloc.dart';
|
||||
import '../../bloc/technical/asset_technical_state.dart';
|
||||
import '../../models/asset_model.dart';
|
||||
import '../../models/fundamental_data_model.dart';
|
||||
import 'package:url_launcher/url_launcher.dart';
|
||||
|
||||
class AssetHeroHeader extends StatelessWidget {
|
||||
@@ -20,35 +20,31 @@ class AssetHeroHeader extends StatelessWidget {
|
||||
const AssetHeroHeader({
|
||||
super.key,
|
||||
this.onExchangeChanged,
|
||||
this.onForceRefresh, required this.isin, required this.name, this.symbol,
|
||||
this.onForceRefresh,
|
||||
required this.isin,
|
||||
required this.name,
|
||||
this.symbol,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = AppTheme.activePreset;
|
||||
|
||||
return BlocBuilder<AssetHeaderBloc, AssetHeaderState>(
|
||||
builder: (context, state) {
|
||||
double? price;
|
||||
String currency = 'EUR';
|
||||
List<AssetTickerOption> tickerOptions = [
|
||||
AssetTickerOption(ticker: 'Loading', exchange: 'Loading', tradingCurrency: '', currentPrice: 0.0)
|
||||
return BlocBuilder<AssetFundamentalsBloc, AssetFundamentalsState>(
|
||||
builder: (context, fundState) {
|
||||
String displayName = name;
|
||||
final String? logoUrl = isin.isNotEmpty ? '/api/v1/logo/$isin' : null;
|
||||
List<TickerModel> tickerOptions = [
|
||||
TickerModel(ticker: symbol ?? 'Loading', exchange: 'Loading', tradingCurrency: '', currentPrice: null)
|
||||
];
|
||||
|
||||
AssetModel? asset;
|
||||
if (state is AssetHeaderLoaded) {
|
||||
asset = state.data;
|
||||
} else if (state is AssetHeaderLoading) {
|
||||
asset = state.previousData;
|
||||
}
|
||||
|
||||
if (asset != null) {
|
||||
//name = asset.name.isNotEmpty ? asset.name : symbol;
|
||||
currency = asset.currency.isNotEmpty ? asset.currency : 'EUR';
|
||||
price = asset.currentPrice;
|
||||
|
||||
if (asset.tickers.isNotEmpty) {
|
||||
tickerOptions = asset.tickers;
|
||||
if (fundState is AssetFundamentalsLoaded && fundState.data != null) {
|
||||
final data = fundState.data!;
|
||||
if (data.companyName.isNotEmpty) {
|
||||
displayName = data.companyName;
|
||||
}
|
||||
if (data.availableTickers.isNotEmpty) {
|
||||
tickerOptions = data.availableTickers;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,14 +84,14 @@ class AssetHeroHeader extends StatelessWidget {
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
],
|
||||
AssetLogoWidget(symbolOrName: isin, imageUrl: asset?.image, size: 48),
|
||||
AssetLogoWidget(symbolOrName: isin, imageUrl: logoUrl, size: 48),
|
||||
const SizedBox(width: 16),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
SelectableText(
|
||||
name,
|
||||
displayName,
|
||||
style: TextStyle(
|
||||
fontSize: 24,
|
||||
fontWeight: FontWeight.w900,
|
||||
@@ -138,7 +134,7 @@ class AssetHeroHeader extends StatelessWidget {
|
||||
onPressed: onForceRefresh,
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
FavoriteStarButton(symbol: symbol, identifier: isin, name: name),
|
||||
FavoriteStarButton(symbol: symbol, identifier: isin, name: displayName),
|
||||
],
|
||||
),
|
||||
],
|
||||
@@ -150,10 +146,8 @@ class AssetHeroHeader extends StatelessWidget {
|
||||
children: [
|
||||
BlocBuilder<AssetTechnicalBloc, AssetTechnicalState>(
|
||||
builder: (context, taState) {
|
||||
double? livePrice = price;
|
||||
String liveCurrency = selectedOption.tradingCurrency.isNotEmpty
|
||||
? selectedOption.tradingCurrency
|
||||
: currency;
|
||||
double? livePrice = selectedOption.currentPrice;
|
||||
String liveCurrency = selectedOption.tradingCurrency ?? 'EUR';
|
||||
|
||||
if (taState is AssetTechnicalLoaded && taState.data != null) {
|
||||
if (taState.data!.candles.isNotEmpty) {
|
||||
@@ -219,12 +213,12 @@ class AssetHeroHeader extends StatelessWidget {
|
||||
(t) => t.ticker == newTicker,
|
||||
orElse: () => tickerOptions.first,
|
||||
);
|
||||
onExchangeChanged!(opt.exchange, opt.ticker);
|
||||
onExchangeChanged!(opt.exchange ?? 'Unknown', opt.ticker);
|
||||
}
|
||||
},
|
||||
itemBuilder: (context) {
|
||||
return tickerOptions.map((opt) {
|
||||
final ex = opt.exchange;
|
||||
final ex = opt.exchange ?? 'Unknown';
|
||||
final tick = opt.ticker;
|
||||
final label = '$tick ($ex)';
|
||||
final isSelected = tick == symbol || ex == symbol;
|
||||
@@ -263,7 +257,7 @@ class AssetHeroHeader extends StatelessWidget {
|
||||
Icon(Icons.business, size: 14, color: theme.accentColor),
|
||||
const SizedBox(width: 6),
|
||||
Text(
|
||||
'${selectedOption.ticker} (${selectedOption.exchange})',
|
||||
'${selectedOption.ticker} (${selectedOption.exchange ?? 'Unknown'})',
|
||||
style: TextStyle(
|
||||
fontSize: 13,
|
||||
fontWeight: FontWeight.bold,
|
||||
@@ -285,3 +279,4 @@ class AssetHeroHeader extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user