edit users in club-settings

This commit is contained in:
beo3000 2026-01-02 20:58:49 +01:00
parent f9e72d095b
commit 51b8c2dbd4
4 changed files with 279 additions and 5 deletions

View File

@ -613,6 +613,9 @@ public class UserService : IUserService
await _appDb.SaveChangesAsync(ct);
// Assign default Viewer role to new member
await AssignClubRoleAsync(userProfileId, clubId, "Viewer", approvedById, ct);
// Send notification to user
var identityUser = await _userManager.FindByIdAsync(membership.UserProfile.IdentityUserId.ToString());
if (identityUser?.Email != null)

View File

@ -25,7 +25,14 @@
[CascadingParameter]
private HttpContext HttpContext { get; set; } = default!;
private IComponentRenderMode? RenderModeForPage => HttpContext.Request.Path.StartsWithSegments("/Account")
? new InteractiveServerRenderMode(prerender: false)
: new InteractiveServerRenderMode(prerender: true);
private IComponentRenderMode? RenderModeForPage
{
get
{
var path = HttpContext.Request.Path;
var disablePrerender = path.StartsWithSegments("/Account")
|| path.StartsWithSegments("/settings");
return new InteractiveServerRenderMode(prerender: !disablePrerender);
}
}
}

View File

@ -0,0 +1,132 @@
@using Koogle.Application.DTOs
@using Koogle.Application.Interfaces
@using Koogle.Domain.Enums
@inject IUserService UserService
@inject ISnackbar Snackbar
<MudDialog>
<DialogContent>
<MudText Typo="Typo.subtitle1" Class="mb-3">Rollen fuer @User.DisplayName</MudText>
<MudPaper Class="pa-3" Elevation="1">
<MudStack Row="true" Spacing="2" Wrap="Wrap.Wrap">
@foreach (var role in _availableRoles)
{
var hasRole = _currentRoles.Contains(role);
<MudChip T="string"
Color="@(hasRole ? Color.Primary : Color.Default)"
Variant="@(hasRole ? Variant.Filled : Variant.Outlined)"
OnClick="@(() => ToggleRole(role, hasRole))"
Disabled="_isProcessing">
@GetRoleDisplayName(role)
</MudChip>
}
</MudStack>
</MudPaper>
<MudDivider Class="my-4" />
<MudButton Size="Size.Small"
Color="Color.Error"
Variant="Variant.Text"
StartIcon="@Icons.Material.Filled.RemoveCircle"
OnClick="RemoveFromClub"
Disabled="_isProcessing">
Aus Verein entfernen
</MudButton>
</DialogContent>
<DialogActions>
<MudButton OnClick="Close">Schliessen</MudButton>
</DialogActions>
</MudDialog>
@code {
[CascadingParameter] private IMudDialogInstance MudDialog { get; set; } = null!;
[Parameter] public UserDto User { get; set; } = null!;
[Parameter] public Guid ClubId { get; set; }
[Parameter] public Guid CurrentUserProfileId { get; set; }
// Available roles for club-admin (no SuperAdmin)
private readonly string[] _availableRoles = { UserRole.Viewer, UserRole.Editor, UserRole.Admin };
private List<string> _currentRoles = new();
private bool _isProcessing;
private bool _hasChanges;
protected override void OnInitialized()
{
var membership = User.ClubMemberships.FirstOrDefault(m => m.ClubId == ClubId);
_currentRoles = membership?.Roles.ToList() ?? new List<string>();
}
private static string GetRoleDisplayName(string role) => role switch
{
UserRole.Viewer => "Betrachter",
UserRole.Editor => "Bearbeiter",
UserRole.Admin => "Administrator",
_ => role
};
private async Task ToggleRole(string role, bool currentlyHasRole)
{
_isProcessing = true;
try
{
bool success;
if (currentlyHasRole)
{
success = await UserService.RemoveClubRoleAsync(User.ProfileId, ClubId, role);
}
else
{
success = await UserService.AssignClubRoleAsync(User.ProfileId, ClubId, role, CurrentUserProfileId);
}
if (success)
{
if (currentlyHasRole)
_currentRoles.Remove(role);
else
_currentRoles.Add(role);
_hasChanges = true;
Snackbar.Add(currentlyHasRole ? "Rolle entfernt" : "Rolle hinzugefuegt", Severity.Success);
StateHasChanged();
}
else
{
Snackbar.Add("Fehler beim Aendern der Rolle", Severity.Error);
}
}
finally
{
_isProcessing = false;
}
}
private async Task RemoveFromClub()
{
_isProcessing = true;
try
{
var success = await UserService.RemoveUserFromClubAsync(User.ProfileId, ClubId);
if (success)
{
_hasChanges = true;
Snackbar.Add("Aus Verein entfernt", Severity.Success);
MudDialog.Close(DialogResult.Ok(_hasChanges));
}
else
{
Snackbar.Add("Fehler beim Entfernen", Severity.Error);
}
}
finally
{
_isProcessing = false;
}
}
private void Close() => MudDialog.Close(DialogResult.Ok(_hasChanges));
}

View File

@ -196,6 +196,61 @@ else
</MudCardContent>
</MudCard>
</MudTabPanel>
<MudTabPanel Text="Mitglieder" BadgeData="@(_clubMembers.Count)" BadgeColor="Color.Primary">
<MudCard Class="mt-4">
<MudCardContent>
@if (_isLoadingMembers)
{
<MudProgressCircular Indeterminate="true" Size="Size.Small" />
}
else if (!_clubMembers.Any())
{
<MudAlert Severity="Severity.Info">Keine Mitglieder vorhanden.</MudAlert>
}
else
{
<MudTable Items="_clubMembers" Dense="true" Hover="true">
<HeaderContent>
<MudTh>Name</MudTh>
<MudTh>E-Mail</MudTh>
<MudTh>Rollen</MudTh>
<MudTh>Aktionen</MudTh>
</HeaderContent>
<RowTemplate>
<MudTd DataLabel="Name">@context.DisplayName</MudTd>
<MudTd DataLabel="E-Mail">@context.Identity.Email</MudTd>
<MudTd DataLabel="Rollen">
@{
var membership = context.ClubMemberships.FirstOrDefault(m => m.ClubId == CurrentClubContext.ClubId);
if (membership != null && membership.Roles.Any())
{
@foreach (var role in membership.Roles)
{
<MudChip T="string" Size="Size.Small" Color="GetRoleColor(role)" Class="mr-1">
@GetRoleDisplayName(role)
</MudChip>
}
}
else
{
<MudText Typo="Typo.caption" Color="Color.Warning">Keine Rolle</MudText>
}
}
</MudTd>
<MudTd DataLabel="Aktionen">
<MudTooltip Text="Rollen verwalten">
<MudIconButton Icon="@Icons.Material.Filled.Security"
Size="Size.Small"
OnClick="@(() => OpenMemberRolesDialog(context))" />
</MudTooltip>
</MudTd>
</RowTemplate>
</MudTable>
}
</MudCardContent>
</MudCard>
</MudTabPanel>
</MudTabs>
}
@ -204,9 +259,11 @@ else
private bool _isLoading = true;
private bool _isLoadingInvitations = true;
private bool _isLoadingPending = true;
private bool _isLoadingMembers = true;
private int _activeTabIndex = 0;
private List<ClubInvitationDto> _invitations = new();
private List<PendingMembershipDto> _pendingMemberships = new();
private List<UserDto> _clubMembers = new();
protected override async Task OnInitializedAsync()
{
@ -217,19 +274,34 @@ else
private async Task LoadAllDataAsync()
{
_isLoading = true;
_isLoadingInvitations = true;
_isLoadingPending = true;
_isLoadingMembers = true;
try
{
var clubId = CurrentClubContext.ClubId;
if (clubId != Guid.Empty)
{
_club = await ClubService.GetByIdAsync(clubId);
await LoadInvitationsAsync();
await LoadPendingMembershipsAsync();
_isLoading = false;
_invitations = (await ClubService.GetInvitationsByClubAsync(clubId)).ToList();
_isLoadingInvitations = false;
_pendingMemberships = (await UserService.GetPendingMembershipsAsync(clubId)).ToList();
_isLoadingPending = false;
_clubMembers = (await UserService.GetUsersByClubAsync(clubId)).ToList();
_isLoadingMembers = false;
}
}
finally
{
_isLoading = false;
_isLoadingInvitations = false;
_isLoadingPending = false;
_isLoadingMembers = false;
}
}
@ -267,6 +339,23 @@ else
}
}
private async Task LoadMembersAsync()
{
_isLoadingMembers = true;
try
{
var clubId = CurrentClubContext.ClubId;
if (clubId != Guid.Empty)
{
_clubMembers = (await UserService.GetUsersByClubAsync(clubId)).ToList();
}
}
finally
{
_isLoadingMembers = false;
}
}
private void ClearError()
{
Dispatcher.Dispatch(new ClearClubErrorAction());
@ -461,4 +550,47 @@ else
}
}
}
private static string GetRoleDisplayName(string role) => role switch
{
UserRole.Viewer => "Betrachter",
UserRole.Editor => "Bearbeiter",
UserRole.Admin => "Administrator",
_ => role
};
private static Color GetRoleColor(string role) => role switch
{
UserRole.Admin => Color.Error,
UserRole.Editor => Color.Warning,
UserRole.Viewer => Color.Info,
_ => Color.Default
};
private async Task OpenMemberRolesDialog(UserDto user)
{
var currentUser = await UserService.GetCurrentUserAsync();
if (currentUser == null)
{
Snackbar.Add("Nicht angemeldet", Severity.Error);
return;
}
var parameters = new DialogParameters
{
{ "User", user },
{ "ClubId", CurrentClubContext.ClubId },
{ "CurrentUserProfileId", currentUser.ProfileId }
};
var options = new DialogOptions { CloseButton = true, MaxWidth = MaxWidth.Small };
var dialog = await DialogService.ShowAsync<ClubMemberRolesDialog>("Rollen verwalten", parameters, options);
var result = await dialog.Result;
if (result != null && !result.Canceled && result.Data is bool hasChanges && hasChanges)
{
await LoadMembersAsync();
StateHasChanged();
}
}
}