From ec50e971a94471e47201eb1047b4ba4c6aecd2f8 Mon Sep 17 00:00:00 2001 From: beo3000 Date: Thu, 25 Dec 2025 20:53:41 +0100 Subject: [PATCH] feat(G5): add PendingMembershipsWidget MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - new PendingMembershipsWidget.razor shows pending membership count - only visible to club admins/super admins - integrated into Dashboard.razor - click navigates to admin users page 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- .../Components/Pages/Dashboard.razor | 6 ++ .../Shared/PendingMembershipsWidget.razor | 90 +++++++++++++++++++ 2 files changed, 96 insertions(+) create mode 100644 src/Koogle.Web/Components/Shared/PendingMembershipsWidget.razor diff --git a/src/Koogle.Web/Components/Pages/Dashboard.razor b/src/Koogle.Web/Components/Pages/Dashboard.razor index ab079c6..b08a202 100644 --- a/src/Koogle.Web/Components/Pages/Dashboard.razor +++ b/src/Koogle.Web/Components/Pages/Dashboard.razor @@ -4,6 +4,7 @@ @using Koogle.Application.DTOs @using Koogle.Application.Interfaces @using Koogle.Domain.Enums +@using Koogle.Web.Components.Shared @using Microsoft.AspNetCore.Authorization @inject IDashboardService DashboardService @@ -102,6 +103,11 @@ else if (_dashboard is not null) + + + + + diff --git a/src/Koogle.Web/Components/Shared/PendingMembershipsWidget.razor b/src/Koogle.Web/Components/Shared/PendingMembershipsWidget.razor new file mode 100644 index 0000000..4b17b31 --- /dev/null +++ b/src/Koogle.Web/Components/Shared/PendingMembershipsWidget.razor @@ -0,0 +1,90 @@ +@using Fluxor +@using Koogle.Application.DTOs +@using Koogle.Application.Interfaces +@using Koogle.Web.Store.AuthState + +@inherits Fluxor.Blazor.Web.Components.FluxorComponent + +@inject IUserService UserService +@inject IState AuthState +@inject NavigationManager NavigationManager +@inject ISnackbar Snackbar + +@if (_isLoading) +{ + +} +else if (_pendingCount > 0) +{ + + + + + + Offene Beitrittsanträge + + @(_pendingCount == 1 ? "1 Antrag wartet auf Freigabe" : $"{_pendingCount} Anträge warten auf Freigabe") + + + +} + +@code { + private int _pendingCount; + private bool _isLoading = true; + + protected override async Task OnInitializedAsync() + { + await base.OnInitializedAsync(); + await LoadPendingCountAsync(); + } + + private async Task LoadPendingCountAsync() + { + try + { + _isLoading = true; + var state = AuthState.Value; + var clubId = state.CurrentClub?.ClubId ?? Guid.Empty; + + if (clubId == Guid.Empty) + { + _pendingCount = 0; + return; + } + + // Only load for club admins or super admins + if (!state.IsClubAdmin && !state.IsSuperAdmin) + { + _pendingCount = 0; + return; + } + + var pending = await UserService.GetPendingMembershipsAsync(clubId); + _pendingCount = pending.Count; + } + catch (Exception ex) + { + Snackbar.Add($"Fehler beim Laden der Anträge: {ex.Message}", Severity.Error); + _pendingCount = 0; + } + finally + { + _isLoading = false; + } + } + + /// + /// Reloads pending membership count. + /// + public async Task RefreshAsync() + { + await LoadPendingCountAsync(); + StateHasChanged(); + } + + private void NavigateToUsers() + { + NavigationManager.NavigateTo("/admin/users"); + } +}