refactor(app): implement year filtering for accounts and enhance dashboard PDF generation
This commit is contained in:
@@ -27,7 +27,7 @@
|
||||
|
||||
<div class="d-flex justify-content-end gap-2">
|
||||
<button class="btn btn-success" @onclick="Save"
|
||||
disabled="@(!CanSave)"><i class="bi bi-arrow-left-right"></i> @(EditEntry != null ? "Speichern" : "Umbuchen")</button>
|
||||
disabled="@(!CanSave)"><i class="bi bi-arrow-left-right"></i> @(EditEntry != null ? "Speichern" : "Hinzufügen")</button>
|
||||
<button class="btn btn-outline-secondary" @onclick="Cancel"><i class="bi bi-x-lg"></i> Abbrechen</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -39,8 +39,8 @@
|
||||
<i class="bi bi-file-earmark-pdf"></i> PDF
|
||||
</button>
|
||||
|
|
||||
<button class="btn btn-nav @(selectedYear.HasValue ? "btn-primary" : "btn-outline-secondary")" @onclick="OpenYearFilterDialog">
|
||||
<i class="bi bi-funnel"></i> Filter<br>@GetFilterLabel()
|
||||
<button class="btn btn-nav btn-primary" @onclick="OpenYearFilterDialog">
|
||||
<i class="bi bi-funnel"></i> Ansicht<br>@GetFilterLabel()
|
||||
</button>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
@inject ISettingsService SettingsService
|
||||
@inject IPdfStatementService PdfStatementService
|
||||
@inject IFileSaveService FileSaveService
|
||||
@inject IEntryService EntryService
|
||||
@inject NavigationManager NavigationManager
|
||||
|
||||
<div class="container-fluid">
|
||||
@@ -34,6 +35,10 @@
|
||||
<button class="btn-nav btn-dark" @onclick="HandleDashboardExportAsync">
|
||||
<i class="bi bi-file-earmark-pdf"></i> PDF
|
||||
</button>
|
||||
|
|
||||
<button class="btn btn-nav btn-primary" @onclick="OpenYearFilterDialog">
|
||||
<i class="bi bi-funnel"></i> Ansicht<br>@GetFilterLabel()
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@if (accounts != null && accounts.Any())
|
||||
@@ -107,3 +112,29 @@
|
||||
OnCancel="CancelRestoreConfirm" />
|
||||
}
|
||||
|
||||
@if (showYearFilterDialog)
|
||||
{
|
||||
<div class="dialog-backdrop" @onclick="CloseYearFilterDialog">
|
||||
<div class="dialog-content" @onclick:stopPropagation="true">
|
||||
<h5>Filter auswählen</h5>
|
||||
<p class="text-muted mb-3">Wähle ein Jahr oder alle Buchungen.</p>
|
||||
<div class="filter-options-grid">
|
||||
<button class="btn @(selectedYear.HasValue ? "btn-outline-secondary" : "btn-primary")" @onclick="() => SelectFilterYear(null)">
|
||||
Alle Buchungen
|
||||
</button>
|
||||
@foreach (var year in availableYears)
|
||||
{
|
||||
<button class="btn @(selectedYear == year ? "btn-primary" : "btn-outline-secondary")" @onclick="() => SelectFilterYear(year)">
|
||||
@year
|
||||
</button>
|
||||
}
|
||||
</div>
|
||||
<div class="d-flex justify-content-end mt-3">
|
||||
<button class="btn btn-outline-secondary" @onclick="CloseYearFilterDialog">
|
||||
<i class="bi bi-x-lg"></i> Schließen
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,9 @@ public partial class Dashboard
|
||||
private bool showAddAccount;
|
||||
private bool showEditClubName;
|
||||
private bool showRestoreConfirm;
|
||||
private bool showYearFilterDialog;
|
||||
private int? selectedYear = DateTime.Now.Year;
|
||||
private List<int> availableYears = [];
|
||||
private string clubName = string.Empty;
|
||||
private string? operationMessage;
|
||||
private string operationMessageClass = "alert-info";
|
||||
@@ -31,16 +34,22 @@ public partial class Dashboard
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
await LoadClubName();
|
||||
await LoadAccounts();
|
||||
await LoadAll();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Data Loading
|
||||
|
||||
private async Task LoadAll()
|
||||
{
|
||||
await LoadAccounts();
|
||||
availableYears = await EntryService.GetAllEntryYearsAsync();
|
||||
}
|
||||
|
||||
private async Task LoadAccounts()
|
||||
{
|
||||
accounts = await AccountService.GetAllAccountsAsync();
|
||||
accounts = await AccountService.GetAllAccountsAsync(selectedYear);
|
||||
}
|
||||
|
||||
private async Task LoadClubName()
|
||||
@@ -56,7 +65,7 @@ public partial class Dashboard
|
||||
{
|
||||
await AccountService.CreateAccountAsync(name);
|
||||
showAddAccount = false;
|
||||
await LoadAccounts();
|
||||
await LoadAll();
|
||||
}
|
||||
|
||||
private async Task HandleSaveClubName(string newName)
|
||||
@@ -104,8 +113,26 @@ public partial class Dashboard
|
||||
|
||||
private async Task HandleDashboardExportAsync()
|
||||
{
|
||||
var pdf = await PdfStatementService.GenerateDashboardStatementAsync();
|
||||
savedPdfPath = await FileSaveService.SaveFileAsync(pdf, $"{DisplayClubName}_Übersicht.pdf");
|
||||
var pdf = await PdfStatementService.GenerateDashboardStatementAsync(selectedYear);
|
||||
var suffix = selectedYear.HasValue ? $"_{selectedYear.Value}" : "_Gesamt";
|
||||
savedPdfPath = await FileSaveService.SaveFileAsync(pdf, $"{DisplayClubName}_Übersicht{suffix}.pdf");
|
||||
}
|
||||
|
||||
private void OpenYearFilterDialog()
|
||||
{
|
||||
showYearFilterDialog = true;
|
||||
}
|
||||
|
||||
private void CloseYearFilterDialog()
|
||||
{
|
||||
showYearFilterDialog = false;
|
||||
}
|
||||
|
||||
private async Task SelectFilterYear(int? year)
|
||||
{
|
||||
selectedYear = year;
|
||||
showYearFilterDialog = false;
|
||||
await LoadAll();
|
||||
}
|
||||
|
||||
private async Task HandleOpenSavedPdf()
|
||||
@@ -138,5 +165,7 @@ public partial class Dashboard
|
||||
return amount.ToString("N2", CultureInfo.GetCultureInfo("de-DE")) + " €";
|
||||
}
|
||||
|
||||
private string GetFilterLabel() => selectedYear?.ToString() ?? "Alle";
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ namespace Duempelkas.App.Services;
|
||||
public interface IAccountService
|
||||
{
|
||||
Task<List<AccountSummaryDto>> GetAllAccountsAsync();
|
||||
Task<List<AccountSummaryDto>> GetAllAccountsAsync(int? year);
|
||||
Task<AccountSummaryDto> GetAccountAsync(int accountId);
|
||||
Task<AccountSummaryDto> CreateAccountAsync(string name);
|
||||
Task RenameAccountAsync(int accountId, string newName);
|
||||
|
||||
@@ -8,6 +8,7 @@ public interface IEntryService
|
||||
Task<List<EntryDto>> GetEntriesAsync(int accountId, int? year);
|
||||
Task<List<EntryDto>> GetEntriesAsync(int accountId, bool currentYearOnly);
|
||||
Task<List<int>> GetEntryYearsAsync(int accountId);
|
||||
Task<List<int>> GetAllEntryYearsAsync();
|
||||
Task<EntryDto> CreateEntryAsync(int accountId, EntryType type, DateTime date, string title, decimal amount);
|
||||
Task CreateTransferAsync(int sourceAccountId, int targetAccountId, DateTime date, string title, decimal amount);
|
||||
Task DeleteEntryAsync(int entryId);
|
||||
|
||||
@@ -5,4 +5,5 @@ public interface IPdfStatementService
|
||||
Task<byte[]> GenerateStatementAsync(int accountId, int? year);
|
||||
Task<byte[]> GenerateStatementAsync(int accountId, bool currentYearOnly);
|
||||
Task<byte[]> GenerateDashboardStatementAsync();
|
||||
Task<byte[]> GenerateDashboardStatementAsync(int? year);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user