using IBKRTrader.Core.Time; using IBKRTrader.Core.Modularity; using IBKRTrader.Core.Settings; using IBKRTrader.Core.Trading; using IBKRTrader.Core.Workers; using Microsoft.Extensions.Configuration; namespace IBKRTrader.UI.Views; /// Core-View: Gesamtüberblick (Trading-Modus, aggregierte Kennzahlen, geladene Module). public sealed class DashboardView : Form { private readonly DashboardService _dashboard; private readonly SettingsService _settings; private readonly IReadOnlyList _modules; private readonly IConfiguration _config; private readonly int _workerCount; private readonly Label _lblMode = new() { AutoSize = true, Location = new Point(20, 20), Font = new Font("Segoe UI", 13f, FontStyle.Bold) }; private readonly Label _lblStats = new() { AutoSize = true, Location = new Point(20, 60) }; private readonly Label _lblStatus = new() { AutoSize = true, Location = new Point(20, 90), ForeColor = SystemColors.GrayText }; private readonly DataGridView _modulesGrid = new() { Location = new Point(20, 130), Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right, ReadOnly = true, AllowUserToAddRows = false, RowHeadersVisible = false, AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill }; public DashboardView( DashboardService dashboard, SettingsService settings, IEnumerable modules, IConfiguration config, IEnumerable workers) { _dashboard = dashboard; _settings = settings; _modules = modules.ToList(); _config = config; _workerCount = workers.Count(); Text = "Dashboard"; Width = 900; Height = 560; StartPosition = FormStartPosition.CenterScreen; MinimumSize = new Size(600, 400); var modLabel = new Label { Text = "Geladene Module:", Location = new Point(20, 108), AutoSize = true }; var refresh = new Button { Text = "Aktualisieren", Location = new Point(760, 18), Width = 110, Anchor = AnchorStyles.Top | AnchorStyles.Right }; refresh.Click += async (_, _) => await RefreshAsync(); _modulesGrid.Size = new Size(ClientSize.Width - 40, ClientSize.Height - 150); Controls.Add(_lblMode); Controls.Add(_lblStats); Controls.Add(_lblStatus); Controls.Add(modLabel); Controls.Add(_modulesGrid); Controls.Add(refresh); } protected override async void OnShown(EventArgs e) { base.OnShown(e); await RefreshAsync(); } private async Task RefreshAsync() { var t = _settings.Settings.Trading; _lblMode.Text = $"Trading: {t.Mode} – {(t.TradingEnabled ? "AKTIV" : "inaktiv")}"; _lblMode.ForeColor = t.TradingEnabled ? Color.SeaGreen : SystemColors.GrayText; _modulesGrid.DataSource = _modules .Select(m => new { Modul = m.Name, Präfix = m.DbPrefix, Status = m.GetActivationBlocker(_config) ?? "aktivierbar" }) .ToList(); try { var snap = await _dashboard.GetSnapshotAsync(); _lblStats.Text = $"Offene Positionen: {snap.OpenPositions} | Exposure: {snap.TotalExposure:N2} | " + $"Trades gesamt: {snap.TotalTrades} | Worker/Services: {_workerCount}"; _lblStatus.Text = $"Aktualisiert: {AppTimeZone.Now:HH:mm:ss}"; } catch (Exception ex) { _lblStats.Text = $"Kennzahlen n/v | Worker/Services: {_workerCount}"; _lblStatus.Text = $"DB nicht erreichbar: {ex.Message}"; } } }