diff --git a/src/Koogle.Web/Components/Shared/DayEvaluationComponent.razor b/src/Koogle.Web/Components/Shared/DayEvaluationComponent.razor new file mode 100644 index 0000000..153389a --- /dev/null +++ b/src/Koogle.Web/Components/Shared/DayEvaluationComponent.razor @@ -0,0 +1,186 @@ +@using Koogle.Application.DTOs +@using Koogle.Application.Interfaces +@using Koogle.Domain.Enums + +@inject IPersonExpenseService PersonExpenseService +@inject ISnackbar Snackbar +@inject NavigationManager NavigationManager + +@if (_isLoading) +{ + +} +else if (_error is not null) +{ + @_error +} +else if (_evaluation is not null) +{ + + + + Auswertung: @_evaluation.PostDate.ToString("dd.MM.yyyy") + + + + @GetStatusLabel(_evaluation.Status) + + + + + +
+ + Gesamt: @_evaluation.TotalAmount.ToString("C") + + + @_evaluation.ExpenseCount Strafen + +
+ + @if (_evaluation.PersonEvaluations.Count == 0) + { + Keine Strafen erfasst + } + else + { + + + Person + Offen + Bezahlt + Gesamt + Anzahl + + + + @if (ShowPersonLinks) + { + + @context.PersonName + + } + else + { + @context.PersonName + } + + + @if (context.OpenAmount > 0) + { + @context.OpenAmount.ToString("C") + } + else + { + - + } + + + @if (context.PaidAmount > 0) + { + @context.PaidAmount.ToString("C") + } + else + { + - + } + + + @context.TotalAmount.ToString("C") + + + @context.ExpenseCount + + + + } +
+
+} + +@code { + /// + /// The unique identifier of the day to evaluate. + /// + [Parameter] + public Guid DayId { get; set; } + + /// + /// Whether to show links to person details. + /// + [Parameter] + public bool ShowPersonLinks { get; set; } = true; + + /// + /// Event callback when data is loaded. + /// + [Parameter] + public EventCallback OnLoaded { get; set; } + + private DayEvaluationDto? _evaluation; + private bool _isLoading = true; + private string? _error; + + protected override async Task OnParametersSetAsync() + { + if (DayId != Guid.Empty) + { + await LoadEvaluationAsync(); + } + } + + /// + /// Reloads the evaluation data. + /// + public async Task RefreshAsync() + { + await LoadEvaluationAsync(); + } + + private async Task LoadEvaluationAsync() + { + try + { + _isLoading = true; + _error = null; + _evaluation = await PersonExpenseService.GetDayEvaluationAsync(DayId); + + if (OnLoaded.HasDelegate) + { + await OnLoaded.InvokeAsync(_evaluation); + } + } + catch (Exception ex) + { + _error = $"Fehler beim Laden der Auswertung: {ex.Message}"; + Snackbar.Add(_error, Severity.Error); + } + finally + { + _isLoading = false; + } + } + + private static string GetStatusLabel(DayStatus status) => status switch + { + DayStatus.New => "Neu", + DayStatus.Started => "Gestartet", + DayStatus.Postponed => "Verschoben", + DayStatus.Closed => "Abgeschlossen", + _ => status.ToString() + }; + + private static Color GetStatusColor(DayStatus status) => status switch + { + DayStatus.New => Color.Info, + DayStatus.Started => Color.Warning, + DayStatus.Postponed => Color.Secondary, + DayStatus.Closed => Color.Success, + _ => Color.Default + }; + + private void NavigateToPersonDetails(Guid personId) + { + NavigationManager.NavigateTo($"/persons/{personId}"); + } +} diff --git a/src/Koogle.Web/Components/Shared/PersonEvaluationComponent.razor b/src/Koogle.Web/Components/Shared/PersonEvaluationComponent.razor new file mode 100644 index 0000000..685ad8e --- /dev/null +++ b/src/Koogle.Web/Components/Shared/PersonEvaluationComponent.razor @@ -0,0 +1,190 @@ +@using Koogle.Application.DTOs +@using Koogle.Application.Interfaces +@using Koogle.Domain.Enums + +@inject IPersonExpenseService PersonExpenseService +@inject IPersonService PersonService +@inject ISnackbar Snackbar +@inject NavigationManager NavigationManager + +@if (_isLoading) +{ + +} +else if (_error is not null) +{ + @_error +} +else if (_evaluation is not null) +{ + + + + Auswertung: @_evaluation.PersonName + + + + + + +
+ @_evaluation.TotalOpenAmount.ToString("C") + Offen +
+
+ +
+ @_evaluation.TotalPaidAmount.ToString("C") + Bezahlt +
+
+ +
+ @_evaluation.TotalExpenseCount + Strafen +
+
+ +
+ @_evaluation.DaysParticipated + Teilnahmen +
+
+
+ + @if (ShowExpenseDetails && _expenses.Count > 0) + { + + Strafenliste + + + Datum + Strafe + Betrag + Status + + + + @if (ShowDayLinks) + { + + @context.DayPostDate.ToString("dd.MM.yyyy") + + } + else + { + @context.DayPostDate.ToString("dd.MM.yyyy") + } + + @context.Name + @context.Price.ToString("C") + + + @GetExpenseStatusLabel(context.PersonExpenseStatus) + + + + + + + + } +
+
+} + +@code { + /// + /// The unique identifier of the person to evaluate. + /// + [Parameter] + public Guid PersonId { get; set; } + + /// + /// Whether to show the detailed expense list. + /// + [Parameter] + public bool ShowExpenseDetails { get; set; } = true; + + /// + /// Whether to show links to day details. + /// + [Parameter] + public bool ShowDayLinks { get; set; } = true; + + /// + /// Event callback when data is loaded. + /// + [Parameter] + public EventCallback OnLoaded { get; set; } + + private PersonEvaluationSummaryDto? _evaluation; + private List _expenses = []; + private bool _isLoading = true; + private string? _error; + + protected override async Task OnParametersSetAsync() + { + if (PersonId != Guid.Empty) + { + await LoadEvaluationAsync(); + } + } + + /// + /// Reloads the evaluation data. + /// + public async Task RefreshAsync() + { + await LoadEvaluationAsync(); + } + + private async Task LoadEvaluationAsync() + { + try + { + _isLoading = true; + _error = null; + + _evaluation = await PersonExpenseService.GetPersonEvaluationAsync(PersonId); + + if (ShowExpenseDetails) + { + _expenses = await PersonExpenseService.GetByPersonIdAsync(PersonId); + } + + if (OnLoaded.HasDelegate) + { + await OnLoaded.InvokeAsync(_evaluation); + } + } + catch (Exception ex) + { + _error = $"Fehler beim Laden der Auswertung: {ex.Message}"; + Snackbar.Add(_error, Severity.Error); + } + finally + { + _isLoading = false; + } + } + + private static string GetExpenseStatusLabel(PersonExpenseStatus status) => status switch + { + PersonExpenseStatus.Open => "Offen", + PersonExpenseStatus.Done => "Bezahlt", + _ => status.ToString() + }; + + private static Color GetExpenseStatusColor(PersonExpenseStatus status) => status switch + { + PersonExpenseStatus.Open => Color.Warning, + PersonExpenseStatus.Done => Color.Success, + _ => Color.Default + }; + + private void NavigateToDayDetails(Guid dayId) + { + NavigationManager.NavigateTo($"/days/{dayId}"); + } +}