using System; using System.Collections.ObjectModel; using System.Globalization; using CommunityToolkit.Mvvm.ComponentModel; using CryptoPortfolio_Tracker.Models; using LiveChartsCore; using LiveChartsCore.Defaults; using LiveChartsCore.SkiaSharpView; using LiveChartsCore.SkiaSharpView.Painting; using SkiaSharp; namespace CryptoPortfolio_Tracker.ViewModels; public partial class CryptoChartViewModel : ViewModelBase { [ObservableProperty] public partial string CryptocurrencyName { get; set; } = null!; [ObservableProperty] public partial decimal CurrentPrice { get; set; } [ObservableProperty] public partial decimal PriceChangePercentage24H { get; set; } [ObservableProperty] public partial decimal PriceChange24H { get; set; } [ObservableProperty] public partial decimal? MarketCap { get; set; } [ObservableProperty] public partial decimal? Volume24H { get; set; } [ObservableProperty] public partial bool IsPositive { get; set; } [ObservableProperty] public partial bool IsNegative { get; set; } [ObservableProperty] public partial DateTime StartDate { get; set; } [ObservableProperty] public partial DateTime EndDate { get; set; } public ObservableCollection PriceHistory7D { get; } = []; public TimeSpan UnitWidth { get; } = TimeSpan.FromHours(1); public Func DateFormatter { get; } = date => date.ToString("dd.MM HH:mm"); public Func PriceFormatter { get; } = FormatPrice; public SolidColorPaint GridPaint { get; } = new(new SKColor(255, 255, 255, 25)); public SolidColorPaint ChartStroke { get; } = new(new SKColor(0x3B, 0xB3, 0x46)); public ISeries[] Series { get; private set; } = []; public CryptoChartViewModel(Cryptocurrency cryptocurrency) { CryptocurrencyName = cryptocurrency.Name; CurrentPrice = cryptocurrency.CurrentPriceUsd; PriceChangePercentage24H = cryptocurrency.PriceChangePercentage24H ?? 0; PriceChange24H = cryptocurrency.PriceChange24H ?? 0; MarketCap = cryptocurrency.MarketCapUsd; Volume24H = cryptocurrency.Volume24HUsd; IsPositive = cryptocurrency.PriceChangePercentage24H > 0; IsNegative = cryptocurrency.PriceChangePercentage24H < 0; foreach (var point in cryptocurrency.PriceHistory7D) { PriceHistory7D.Add(point); } if (PriceHistory7D.Count > 0) { StartDate = PriceHistory7D[0].DateTime; EndDate = PriceHistory7D[^1].DateTime; } UpdateSeries(); } partial void OnStartDateChanged(DateTime value) { UpdateSeries(); } partial void OnEndDateChanged(DateTime value) { UpdateSeries(); } private void UpdateSeries() { ObservableCollection visiblePoints = []; foreach (var point in PriceHistory7D) { if (point.DateTime >= StartDate && point.DateTime <= EndDate) { visiblePoints.Add(point); } } if (visiblePoints.Count == 0) { Series = []; OnPropertyChanged(nameof(Series)); return; } LineSeries lineSeries = new() { Values = visiblePoints, GeometrySize = 0, Fill = null, GeometryFill = null, GeometryStroke = null, Stroke = ChartStroke, LineSmoothness = 0.2 }; Series = [ lineSeries ]; OnPropertyChanged(nameof(Series)); } private static string FormatPrice(double price) { return price switch { >= 1000 => price.ToString("N0", CultureInfo.InvariantCulture), >= 1 => price.ToString("N2", CultureInfo.InvariantCulture), >= 0.01 => price.ToString("N4", CultureInfo.InvariantCulture), _ => price.ToString("0.########", CultureInfo.InvariantCulture) }; } }