diff --git a/MoneyMap/Models/Dashboard/DashboardModels.cs b/MoneyMap/Models/Dashboard/DashboardModels.cs index daf3a2e..b81845b 100644 --- a/MoneyMap/Models/Dashboard/DashboardModels.cs +++ b/MoneyMap/Models/Dashboard/DashboardModels.cs @@ -47,6 +47,7 @@ namespace MoneyMap.Models.Dashboard public List DebitsAbs { get; set; } = new(); public List Credits { get; set; } = new(); public List Net { get; set; } = new(); + public List RunningBalance { get; set; } = new(); } /// diff --git a/MoneyMap/Pages/Index.cshtml b/MoneyMap/Pages/Index.cshtml index c9d7888..e8dc3dc 100644 --- a/MoneyMap/Pages/Index.cshtml +++ b/MoneyMap/Pages/Index.cshtml @@ -68,7 +68,7 @@
-
Cash flow (last 30 days)
+
Net cash flow (last 30 days)
@@ -180,9 +180,7 @@ const topValues = @Html.Raw(System.Text.Json.JsonSerializer.Serialize(Model.TopCategories.Select(c => c.TotalSpend))); const trendLabels = @Html.Raw(System.Text.Json.JsonSerializer.Serialize(Model.TrendLabels)); - const trendDebits = @Html.Raw(System.Text.Json.JsonSerializer.Serialize(Model.TrendDebitsAbs)); - const trendCredits = @Html.Raw(System.Text.Json.JsonSerializer.Serialize(Model.TrendCredits)); - const trendNet = @Html.Raw(System.Text.Json.JsonSerializer.Serialize(Model.TrendNet)); + const trendBalance = @Html.Raw(System.Text.Json.JsonSerializer.Serialize(Model.TrendRunningBalance)); const catCtx = document.getElementById('categoryChart'); if (catCtx && topLabels.length) { @@ -205,21 +203,46 @@ const trendCtx = document.getElementById('trendChart'); if (trendCtx) { new Chart(trendCtx, { + type: 'line', data: { labels: trendLabels, - datasets: [ - { type: 'bar', label: 'Debits', data: trendDebits, backgroundColor: 'rgba(225,87,89,0.6)' }, - { type: 'bar', label: 'Credits', data: trendCredits, backgroundColor: 'rgba(76,175,80,0.6)' }, - { type: 'line', label: 'Net', data: trendNet, borderColor: '#4e79a7', backgroundColor: 'transparent', tension: 0.2, yAxisID: 'y' } - ] + datasets: [{ + label: 'Net Cash Flow', + data: trendBalance, + borderColor: '#6ea8fe', + backgroundColor: 'rgba(110,168,254,0.15)', + fill: true, + tension: 0.3, + pointRadius: 0, + pointHoverRadius: 5 + }] }, options: { scales: { - y: { beginAtZero: true, ticks: { color: '#adb5bd' }, grid: { color: 'rgba(255,255,255,0.1)' } }, - x: { ticks: { color: '#adb5bd' }, grid: { color: 'rgba(255,255,255,0.1)' } } + y: { + ticks: { + color: '#adb5bd', + callback: function(value) { return '$' + value.toLocaleString(); } + }, + grid: { color: 'rgba(255,255,255,0.1)' } + }, + x: { + ticks: { color: '#adb5bd', maxTicksLimit: 10 }, + grid: { color: 'rgba(255,255,255,0.05)' } + } }, - plugins: { legend: { labels: { color: '#adb5bd' } } }, - maintainAspectRatio: false + plugins: { + legend: { display: false }, + tooltip: { + callbacks: { + label: function(context) { + return '$' + context.parsed.y.toLocaleString(undefined, {minimumFractionDigits: 2, maximumFractionDigits: 2}); + } + } + } + }, + maintainAspectRatio: false, + interaction: { intersect: false, mode: 'index' } } }); } diff --git a/MoneyMap/Pages/Index.cshtml.cs b/MoneyMap/Pages/Index.cshtml.cs index 96c0406..8c85e76 100644 --- a/MoneyMap/Pages/Index.cshtml.cs +++ b/MoneyMap/Pages/Index.cshtml.cs @@ -17,9 +17,7 @@ namespace MoneyMap.Pages public List TopCategories { get; set; } = new(); public List Recent { get; set; } = new(); public List TrendLabels { get; set; } = new(); - public List TrendDebitsAbs { get; set; } = new(); - public List TrendCredits { get; set; } = new(); - public List TrendNet { get; set; } = new(); + public List TrendRunningBalance { get; set; } = new(); public async Task OnGet() { @@ -29,9 +27,7 @@ namespace MoneyMap.Pages TopCategories = dashboard.TopCategories; Recent = dashboard.RecentTransactions; TrendLabels = dashboard.Trends.Labels; - TrendDebitsAbs = dashboard.Trends.DebitsAbs; - TrendCredits = dashboard.Trends.Credits; - TrendNet = dashboard.Trends.Net; + TrendRunningBalance = dashboard.Trends.RunningBalance; } } } diff --git a/MoneyMap/Services/DashboardService.cs b/MoneyMap/Services/DashboardService.cs index 380b70d..268ed08 100644 --- a/MoneyMap/Services/DashboardService.cs +++ b/MoneyMap/Services/DashboardService.cs @@ -231,10 +231,12 @@ namespace MoneyMap.Services var debitsAbs = new List(); var credits = new List(); var net = new List(); + var runningBalance = new List(); + decimal cumulative = 0; for (var d = since; d <= today; d = d.AddDays(1)) { - labels.Add(d.ToString("yyyy-MM-dd")); + labels.Add(d.ToString("MMM d")); if (dict.TryGetValue(d, out var v)) { var debit = v.Debits; @@ -242,6 +244,7 @@ namespace MoneyMap.Services debitsAbs.Add(Math.Abs(debit)); credits.Add(credit); net.Add(credit + debit); + cumulative += credit + debit; } else { @@ -249,6 +252,7 @@ namespace MoneyMap.Services credits.Add(0); net.Add(0); } + runningBalance.Add(cumulative); } return new SpendTrends @@ -256,7 +260,8 @@ namespace MoneyMap.Services Labels = labels, DebitsAbs = debitsAbs, Credits = credits, - Net = net + Net = net, + RunningBalance = runningBalance }; } }