@page "/" @attribute [Authorize] @inject DashboardService DashboardService @inject ITransactionRepository TransactionService @inject ISalaryRepository SalaryService @inject AuthenticationStateProvider AuthStateProvider @inject IJSRuntime Js @using BudgetApp.Data.Entities @implements IAsyncDisposable @rendermode InteractiveServer Dashboard

Dashboard

An overview of your balances, recent and upcoming transactions.

@if (_data is null) {

Loading...

} else if (_data.Accounts.Count == 0) {
Welcome!

Get started by adding an account and then recording transactions.

} else {
Balance Trend
to
@* ── Edit / Add Modal ── *@ @if (_showModal) { }
@if (_data.Accounts.Count > 1) {
Filter: @foreach (var a in _data.Accounts) { }
}
@if (_activeTab == "recent") { @if (FilteredRecent.Count == 0) {

No recent transactions.

} else {
@foreach (var t in FilteredRecent.Skip((_recentPage - 1) * PageSize).Take(PageSize)) {
@t.Description @if (t.RecurrenceType != RecurrenceType.None || t.ParentTransactionId is not null) { 🔁 @GetRecurrenceLabel(t) } @if (t.IsPaid) { ✓ Paid }
@t.Date.ToString("MMM dd, yyyy") @t.Account.Name @if (t.Category is not null) { @(string.IsNullOrEmpty(t.Category.Icon) ? "" : t.Category.Icon + " ")@t.Category.Name }
@(t.Type == TransactionType.Income ? "+" : "−")@t.Account.FormatAmount(t.Amount)
@(t.Type == TransactionType.Income ? "Income" : "Expense")
@if (_selectedTransactionId == t.Id) {
@if (t.IsPaid) { } else { }
}
}
@if (RecentTotalPages > 1) {
Page @_recentPage of @RecentTotalPages
} } } else { @if (FilteredUpcoming.Count == 0) {

No upcoming transactions.

} else {
@foreach (var t in FilteredUpcoming.Skip((_upcomingPage - 1) * PageSize).Take(PageSize)) {
@t.Description @if (t.RecurrenceType != RecurrenceType.None || t.ParentTransactionId is not null) { 🔁 @GetRecurrenceLabel(t) }
@t.Date.ToString("MMM dd, yyyy") @t.Account.Name @if (t.Category is not null) { @(string.IsNullOrEmpty(t.Category.Icon) ? "" : t.Category.Icon + " ")@t.Category.Name }
@(t.Type == TransactionType.Income ? "+" : "−")@t.Account.FormatAmount(t.Amount)
@if (_projectedBalances.TryGetValue(t.Id, out var projected)) { Projected: @t.Account.FormatAmount(projected) } else { @(t.Type == TransactionType.Income ? "Income" : "Expense") }
@if (_selectedTransactionId == t.Id) {
}
}
@if (UpcomingTotalPages > 1) {
Page @_upcomingPage of @UpcomingTotalPages
} } }
@if (_showDeleteModal && _pendingDeleteTransaction is not null) { } } @code { // Modal state // Chart redraw tracking // Time window // Account filter // Pagination // Delete confirmation state }