feat(G5): add PendingMembershipsWidget
- 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 <noreply@anthropic.com>
This commit is contained in:
parent
8e2342fd74
commit
ec50e971a9
|
|
@ -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)
|
|||
</MudCard>
|
||||
</MudItem>
|
||||
|
||||
<!-- Pending Memberships Widget (Admin only) -->
|
||||
<MudItem xs="12">
|
||||
<PendingMembershipsWidget />
|
||||
</MudItem>
|
||||
|
||||
<!-- Top Penalty Recipients -->
|
||||
<MudItem xs="12" md="6">
|
||||
<MudCard Elevation="2">
|
||||
|
|
|
|||
|
|
@ -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> AuthState
|
||||
@inject NavigationManager NavigationManager
|
||||
@inject ISnackbar Snackbar
|
||||
|
||||
@if (_isLoading)
|
||||
{
|
||||
<MudProgressLinear Indeterminate="true" Color="Color.Primary" />
|
||||
}
|
||||
else if (_pendingCount > 0)
|
||||
{
|
||||
<MudCard Elevation="2" Style="cursor: pointer" @onclick="NavigateToUsers">
|
||||
<MudCardContent Class="d-flex flex-column align-center">
|
||||
<MudBadge Content="@_pendingCount" Color="Color.Error" Overlap="true">
|
||||
<MudIcon Icon="@Icons.Material.Filled.PersonAdd" Size="Size.Large" Color="Color.Warning" />
|
||||
</MudBadge>
|
||||
<MudText Typo="Typo.h6" Class="mt-2">Offene Beitrittsanträge</MudText>
|
||||
<MudText Typo="Typo.body2" Color="Color.Secondary">
|
||||
@(_pendingCount == 1 ? "1 Antrag wartet auf Freigabe" : $"{_pendingCount} Anträge warten auf Freigabe")
|
||||
</MudText>
|
||||
</MudCardContent>
|
||||
</MudCard>
|
||||
}
|
||||
|
||||
@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;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reloads pending membership count.
|
||||
/// </summary>
|
||||
public async Task RefreshAsync()
|
||||
{
|
||||
await LoadPendingCountAsync();
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
private void NavigateToUsers()
|
||||
{
|
||||
NavigationManager.NavigateTo("/admin/users");
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue