using System; using System.Globalization; using System.Linq; using System.Windows; using System.Windows.Controls; using AutoBidder.Utilities; namespace AutoBidder.Controls { /// /// Scheda Esporta: sceglie quali aste finiscono in un unico file e lo scrive. /// /// Come gli altri pannelli non conosce gli archivi: costruisce un /// e lascia il lavoro a /// . Qui dentro c'è solo la traduzione fra i campi /// dell'interfaccia e i criteri — e il conteggio in tempo reale, che serve a non /// scoprire dopo un minuto di scrittura che il filtro non selezionava nulla. /// public partial class ExportControl : UserControl { private string? _lastExportPath; public ExportControl() { InitializeComponent(); Loaded += (_, _) => RefreshPreview(); } /// I criteri come sono impostati adesso. public AuctionExportFilter BuildFilter() => new() { From = FromDatePicker.SelectedDate, To = ToDatePicker.SelectedDate, NameContains = string.IsNullOrWhiteSpace(NameFilterTextBox.Text) ? null : NameFilterTextBox.Text.Trim(), IncludeWon = IncludeWonCheckBox.IsChecked == true, IncludeLost = IncludeLostCheckBox.IsChecked == true, IncludeClosed = IncludeClosedCheckBox.IsChecked == true, OnlyComplete = OnlyCompleteCheckBox.IsChecked == true, OnlyWithMyBids = OnlyWithMyBidsCheckBox.IsChecked == true, OnlyWithDossier = OnlyWithDossierCheckBox.IsChecked == true, MinFinalPrice = ParseNumber(MinPriceTextBox.Text), MaxFinalPrice = ParseNumber(MaxPriceTextBox.Text), MaxAuctions = (int)(ParseNumber(MaxAuctionsTextBox.Text) ?? 0), IncludeEvents = IncludeEventsCheckBox.IsChecked == true }; /// /// Ricalcola quante aste corrispondono. Si fa a ogni modifica dei filtri: sapere /// prima che il risultato è vuoto — o che sono duemila — evita di scoprirlo a file /// scritto. /// public void RefreshPreview() { try { var selected = AuctionExporter.Select(BuildFilter()); MatchCountText.Text = selected.Count == 1 ? "1 asta" : $"{selected.Count} aste"; var complete = selected.Count(r => r.IsComplete); CompleteCountText.Text = $"{complete} complete"; ExportButton.IsEnabled = selected.Count > 0; } catch (Exception ex) { MatchCountText.Text = "—"; CompleteCountText.Text = ex.Message; } } /// Mostra l'esito dell'esportazione appena fatta. public void ShowResult(AuctionExportResult result) { if (result.Success) { _lastExportPath = result.Path; var size = result.Bytes >= 1024 * 1024 ? $"{result.Bytes / 1024.0 / 1024.0:F1} MB" : $"{Math.Max(1, result.Bytes / 1024)} kB"; ResultText.Text = $"{result.AuctionCount} aste ({result.WithEvents} con eventi), {size} — {result.Path}"; ResultText.SetResourceReference(ForegroundProperty, "Brush.Text"); OpenLastFileButton.Visibility = Visibility.Visible; } else { ResultText.Text = result.Message; ResultText.SetResourceReference(ForegroundProperty, "Brush.Warning"); OpenLastFileButton.Visibility = Visibility.Collapsed; } } /// Percorso dell'ultimo file scritto, per il pulsante "Apri il file". public string? LastExportPath => _lastExportPath; // ── Eventi dell'interfaccia ────────────────────────────────────── private void PreviewButton_Click(object sender, RoutedEventArgs e) => RefreshPreview(); private void Filter_Changed(object sender, RoutedEventArgs e) => RefreshPreview(); private void Last7Days_Click(object sender, RoutedEventArgs e) => SetPeriod(7); private void Last30Days_Click(object sender, RoutedEventArgs e) => SetPeriod(30); private void SetPeriod(int days) { FromDatePicker.SelectedDate = DateTime.Today.AddDays(-days); ToDatePicker.SelectedDate = DateTime.Today; RefreshPreview(); } private void ResetFiltersButton_Click(object sender, RoutedEventArgs e) { FromDatePicker.SelectedDate = null; ToDatePicker.SelectedDate = null; NameFilterTextBox.Text = ""; MinPriceTextBox.Text = ""; MaxPriceTextBox.Text = ""; MaxAuctionsTextBox.Text = "0"; IncludeWonCheckBox.IsChecked = true; IncludeLostCheckBox.IsChecked = true; IncludeClosedCheckBox.IsChecked = true; OnlyCompleteCheckBox.IsChecked = false; OnlyWithMyBidsCheckBox.IsChecked = false; OnlyWithDossierCheckBox.IsChecked = false; IncludeEventsCheckBox.IsChecked = true; RefreshPreview(); } private void ExportButton_Click(object sender, RoutedEventArgs e) => RaiseEvent(new RoutedEventArgs(ExportRequestedEvent, this)); private void OpenFolderButton_Click(object sender, RoutedEventArgs e) => RaiseEvent(new RoutedEventArgs(OpenExportFolderClickedEvent, this)); private void ClearExportsButton_Click(object sender, RoutedEventArgs e) => RaiseEvent(new RoutedEventArgs(ClearExportsClickedEvent, this)); private void OpenLastFileButton_Click(object sender, RoutedEventArgs e) => RaiseEvent(new RoutedEventArgs(OpenLastFileClickedEvent, this)); /// /// Legge un numero accettando sia la virgola sia il punto: chi scrive "12,50" e chi /// scrive "12.50" intende la stessa cosa, e rifiutarne uno dei due sarebbe pedanteria. /// private static double? ParseNumber(string? text) { if (string.IsNullOrWhiteSpace(text)) return null; var clean = text.Trim().Replace(',', '.'); return double.TryParse(clean, NumberStyles.Any, CultureInfo.InvariantCulture, out var value) ? value : null; } // ── Routed events ──────────────────────────────────────────────── public static readonly RoutedEvent ExportRequestedEvent = EventManager.RegisterRoutedEvent( "ExportRequested", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(ExportControl)); public static readonly RoutedEvent OpenExportFolderClickedEvent = EventManager.RegisterRoutedEvent( "OpenExportFolderClicked", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(ExportControl)); public static readonly RoutedEvent OpenLastFileClickedEvent = EventManager.RegisterRoutedEvent( "OpenLastFileClicked", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(ExportControl)); public static readonly RoutedEvent ClearExportsClickedEvent = EventManager.RegisterRoutedEvent( "ClearExportsClicked", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(ExportControl)); public event RoutedEventHandler ClearExportsClicked { add { AddHandler(ClearExportsClickedEvent, value); } remove { RemoveHandler(ClearExportsClickedEvent, value); } } public event RoutedEventHandler ExportRequested { add { AddHandler(ExportRequestedEvent, value); } remove { RemoveHandler(ExportRequestedEvent, value); } } public event RoutedEventHandler OpenExportFolderClicked { add { AddHandler(OpenExportFolderClickedEvent, value); } remove { RemoveHandler(OpenExportFolderClickedEvent, value); } } public event RoutedEventHandler OpenLastFileClicked { add { AddHandler(OpenLastFileClickedEvent, value); } remove { RemoveHandler(OpenLastFileClickedEvent, value); } } } }