feat(trades): add live execution cockpit, closing cockpit, calculation cards and precision trade settings
This commit is contained in:
@@ -3,17 +3,16 @@ import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import '../../../core/network/api_client.dart';
|
||||
import '../../../core/network/signalr_service.dart';
|
||||
import '../../../core/theme/app_theme.dart';
|
||||
import '../../auth/bloc/auth_bloc.dart';
|
||||
import '../bloc/trade_bloc.dart';
|
||||
import '../bloc/trade_event.dart';
|
||||
import '../bloc/trade_state.dart';
|
||||
import '../models/trade_model.dart';
|
||||
import '../models/trade_acceptance_dto.dart';
|
||||
import '../models/close_trade_request_dto.dart';
|
||||
import '../repositories/trade_repository.dart';
|
||||
import '../widgets/trade_card.dart';
|
||||
import '../widgets/proposed_auto_trades_card.dart';
|
||||
import '../widgets/trade_acceptance_dialog.dart';
|
||||
import '../widgets/trade_execution_dialog.dart';
|
||||
import '../widgets/trade_execution_cockpit.dart';
|
||||
import '../widgets/trade_closing_cockpit.dart';
|
||||
import '../widgets/trade_performance_bar.dart';
|
||||
|
||||
class TradesFeedScreen extends StatelessWidget {
|
||||
@@ -55,28 +54,45 @@ class _TradesFeedScreenContentState extends State<_TradesFeedScreenContent> {
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
Future<void> _handleAcceptProposal(BuildContext context, TradeModel trade) async {
|
||||
final authState = context.read<AuthBloc>().state;
|
||||
final currentUserId = (authState is Authenticated) ? authState.user.userId : 'default_user';
|
||||
void _handleAcceptProposal(BuildContext context, TradeModel trade, {bool isActive = false}) {
|
||||
final tradeBloc = context.read<TradeBloc>();
|
||||
|
||||
final result = await showDialog<TradeAcceptanceDto>(
|
||||
context: context,
|
||||
builder: (ctx) => TradeAcceptanceDialog(
|
||||
trade: trade,
|
||||
theme: AppTheme.darkClassic,
|
||||
userId: currentUserId,
|
||||
),
|
||||
TradeExecutionCockpit.show(
|
||||
context,
|
||||
trade: trade,
|
||||
defaultSymbol: trade.symbol.isNotEmpty ? trade.symbol : trade.isin,
|
||||
isActive: isActive,
|
||||
onAccept: (dto) {
|
||||
tradeBloc.add(AcceptTradeProposalEvent(dto));
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text(isActive ? 'Einstellungen für ${trade.symbol} gespeichert!' : 'Trade für ${trade.symbol} eröffnet!'),
|
||||
backgroundColor: AppTheme.primaryEmerald,
|
||||
behavior: SnackBarBehavior.floating,
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
if (result != null && mounted) {
|
||||
context.read<TradeBloc>().add(AcceptTradeProposalEvent(result));
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: const Text('Trade wird in dein Portfolio übernommen...'),
|
||||
backgroundColor: AppTheme.primaryEmerald,
|
||||
),
|
||||
);
|
||||
}
|
||||
void _handleCloseTrade(BuildContext context, TradeModel trade) {
|
||||
final tradeBloc = context.read<TradeBloc>();
|
||||
|
||||
TradeClosingCockpit.show(
|
||||
context,
|
||||
trade: trade,
|
||||
defaultSymbol: trade.symbol.isNotEmpty ? trade.symbol : trade.isin,
|
||||
onClose: (CloseTradeRequestDto dto) {
|
||||
tradeBloc.add(CloseTrade(trade.id, dto: dto));
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text('Position ${trade.symbol} geschlossen! Realisierter Verkaufskurs: €${dto.userExitPrice.toStringAsFixed(2)}'),
|
||||
backgroundColor: AppTheme.primaryEmerald,
|
||||
behavior: SnackBarBehavior.floating,
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -102,12 +118,12 @@ class _TradesFeedScreenContentState extends State<_TradesFeedScreenContent> {
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const Text(
|
||||
'Live Portfolio & Trading',
|
||||
'Live Portfolio & Trades',
|
||||
style: TextStyle(fontSize: 22, fontWeight: FontWeight.bold, color: Colors.white),
|
||||
),
|
||||
const SizedBox(height: 2),
|
||||
Text(
|
||||
'KI-Erkennungen, Vorschläge & Aktive Positionen',
|
||||
'KI-Guardian Überwachung, Drift-Radar & Order-Cockpit',
|
||||
style: TextStyle(color: AppTheme.textMuted, fontSize: 12),
|
||||
),
|
||||
],
|
||||
@@ -211,11 +227,11 @@ class _TradesFeedScreenContentState extends State<_TradesFeedScreenContent> {
|
||||
scrollDirection: Axis.horizontal,
|
||||
child: Row(
|
||||
children: [
|
||||
_filterChip('Alle', allTrades.length),
|
||||
_filterChip('Offen', activeTrades.length),
|
||||
_filterChip('Vorschläge', proposals.length),
|
||||
_filterChip('Abgelehnt', rejectedTrades.length),
|
||||
_filterChip('Geschlossen', closedTrades.length),
|
||||
_filterChip('Abgelehnt', rejectedTrades.length),
|
||||
_filterChip('Alle', allTrades.length),
|
||||
],
|
||||
),
|
||||
),
|
||||
@@ -228,7 +244,7 @@ class _TradesFeedScreenContentState extends State<_TradesFeedScreenContent> {
|
||||
children: [
|
||||
Icon(Icons.inbox, size: 40, color: AppTheme.textMuted),
|
||||
const SizedBox(height: 8),
|
||||
Text('Keine Trades in der Kategorie "$_selectedFilter" gefunden.', style: TextStyle(color: AppTheme.textMuted, fontSize: 13)),
|
||||
Text('Keine Trades in der Kategorie "$_selectedFilter" vorhanden.', style: TextStyle(color: AppTheme.textMuted, fontSize: 13)),
|
||||
],
|
||||
),
|
||||
),
|
||||
@@ -243,13 +259,8 @@ class _TradesFeedScreenContentState extends State<_TradesFeedScreenContent> {
|
||||
return TradeCard(
|
||||
trade: trade,
|
||||
onAccept: () => _handleAcceptProposal(context, trade),
|
||||
onSettings: () => _showTradeSettingsDialog(context, trade),
|
||||
onClose: () {
|
||||
context.read<TradeBloc>().add(CloseTrade(trade.id));
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(content: Text('Position wird geschlossen...')),
|
||||
);
|
||||
},
|
||||
onSettings: () => _handleAcceptProposal(context, trade, isActive: true),
|
||||
onClose: () => _handleCloseTrade(context, trade),
|
||||
);
|
||||
},
|
||||
),
|
||||
@@ -312,24 +323,5 @@ class _TradesFeedScreenContentState extends State<_TradesFeedScreenContent> {
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void _showTradeSettingsDialog(BuildContext context, TradeModel trade) {
|
||||
final tradeBloc = context.read<TradeBloc>();
|
||||
|
||||
TradeExecutionDialog.show(
|
||||
context,
|
||||
trade: trade,
|
||||
defaultSymbol: trade.symbol,
|
||||
isActive: true,
|
||||
onAccept: (dto) {
|
||||
tradeBloc.add(AcceptTradeProposalEvent(dto));
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text('Einstellungen für ${trade.symbol} gespeichert.'),
|
||||
backgroundColor: AppTheme.primaryEmerald,
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user