feat(G7): add JoinClub page and no-club dashboard message
This commit is contained in:
parent
e8b2154f69
commit
97ea3b35ca
|
|
@ -0,0 +1,231 @@
|
|||
@page "/account/join-club"
|
||||
@attribute [Authorize]
|
||||
|
||||
@using Koogle.Application.DTOs
|
||||
@using Koogle.Application.Interfaces
|
||||
@using Microsoft.AspNetCore.Authorization
|
||||
|
||||
@inject IUserService UserService
|
||||
@inject IClubService ClubService
|
||||
@inject ISnackbar Snackbar
|
||||
@inject NavigationManager NavigationManager
|
||||
|
||||
<PageTitle>Club beitreten</PageTitle>
|
||||
|
||||
<MudContainer MaxWidth="MaxWidth.Small" Class="mt-4">
|
||||
<MudText Typo="Typo.h4" Class="mb-4">Club beitreten</MudText>
|
||||
|
||||
@if (_isLoading)
|
||||
{
|
||||
<MudProgressCircular Indeterminate="true" />
|
||||
}
|
||||
else if (_requestSent)
|
||||
{
|
||||
<MudAlert Severity="Severity.Success" Class="mb-4">
|
||||
<MudText Typo="Typo.body1">
|
||||
Dein Beitrittsantrag wurde erfolgreich gesendet!
|
||||
</MudText>
|
||||
<MudText Typo="Typo.body2" Class="mt-2">
|
||||
Ein Admin des Clubs wird deinen Antrag pruefen. Du erhaeltst eine Benachrichtigung, sobald dein Antrag bearbeitet wurde.
|
||||
</MudText>
|
||||
</MudAlert>
|
||||
<MudButton Variant="Variant.Filled" Color="Color.Primary" OnClick="ResetForm">
|
||||
Weiteren Antrag stellen
|
||||
</MudButton>
|
||||
<MudButton Variant="Variant.Outlined" Color="Color.Default" Class="ml-2" Href="/account/profile">
|
||||
Zum Profil
|
||||
</MudButton>
|
||||
}
|
||||
else
|
||||
{
|
||||
<MudPaper Class="pa-4" Elevation="2">
|
||||
<MudText Typo="Typo.body1" Class="mb-4">
|
||||
Gib den Namen des Clubs ein, dem du beitreten moechtest. Dein Antrag wird vom Club-Admin geprueft.
|
||||
</MudText>
|
||||
|
||||
<MudForm @ref="_form" @bind-IsValid="_isValid">
|
||||
<MudTextField @bind-Value="_clubName"
|
||||
Label="Club-Name"
|
||||
Variant="Variant.Outlined"
|
||||
Required="true"
|
||||
RequiredError="Bitte gib einen Club-Namen ein"
|
||||
Immediate="true"
|
||||
OnKeyUp="OnClubNameKeyUp"
|
||||
Class="mb-3" />
|
||||
|
||||
@if (_searchResult is not null)
|
||||
{
|
||||
<MudAlert Severity="Severity.Info" Class="mb-3">
|
||||
<div class="d-flex justify-space-between align-center">
|
||||
<div>
|
||||
<MudText Typo="Typo.body1"><strong>@_searchResult.Name</strong></MudText>
|
||||
<MudText Typo="Typo.caption">@_searchResult.MemberCount Mitglieder</MudText>
|
||||
</div>
|
||||
<MudIcon Icon="@Icons.Material.Filled.Check" Color="Color.Success" />
|
||||
</div>
|
||||
</MudAlert>
|
||||
}
|
||||
else if (_searched && !string.IsNullOrWhiteSpace(_clubName))
|
||||
{
|
||||
<MudAlert Severity="Severity.Warning" Class="mb-3">
|
||||
Kein Club mit diesem Namen gefunden. Bitte pruefe die Schreibweise.
|
||||
</MudAlert>
|
||||
}
|
||||
|
||||
@if (!string.IsNullOrEmpty(_error))
|
||||
{
|
||||
<MudAlert Severity="Severity.Error" Class="mb-3">@_error</MudAlert>
|
||||
}
|
||||
|
||||
<div class="d-flex gap-2">
|
||||
<MudButton Variant="Variant.Outlined"
|
||||
Color="Color.Primary"
|
||||
OnClick="SearchClub"
|
||||
Disabled="_isSearching || string.IsNullOrWhiteSpace(_clubName)">
|
||||
@if (_isSearching)
|
||||
{
|
||||
<MudProgressCircular Size="Size.Small" Indeterminate="true" Class="mr-2" />
|
||||
}
|
||||
Club suchen
|
||||
</MudButton>
|
||||
|
||||
<MudButton Variant="Variant.Filled"
|
||||
Color="Color.Primary"
|
||||
OnClick="SubmitRequest"
|
||||
Disabled="_isSubmitting || _searchResult is null">
|
||||
@if (_isSubmitting)
|
||||
{
|
||||
<MudProgressCircular Size="Size.Small" Indeterminate="true" Class="mr-2" />
|
||||
}
|
||||
Beitrittsantrag senden
|
||||
</MudButton>
|
||||
</div>
|
||||
</MudForm>
|
||||
</MudPaper>
|
||||
}
|
||||
</MudContainer>
|
||||
|
||||
@code {
|
||||
private MudForm? _form;
|
||||
private bool _isValid;
|
||||
private string _clubName = "";
|
||||
private ClubDto? _searchResult;
|
||||
private bool _searched;
|
||||
private bool _isLoading;
|
||||
private bool _isSearching;
|
||||
private bool _isSubmitting;
|
||||
private bool _requestSent;
|
||||
private string? _error;
|
||||
private UserDto? _currentUser;
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
_isLoading = true;
|
||||
try
|
||||
{
|
||||
_currentUser = await UserService.GetCurrentUserAsync();
|
||||
}
|
||||
finally
|
||||
{
|
||||
_isLoading = false;
|
||||
}
|
||||
}
|
||||
|
||||
private async Task OnClubNameKeyUp(KeyboardEventArgs e)
|
||||
{
|
||||
// Reset search result when user types
|
||||
if (_searched)
|
||||
{
|
||||
_searched = false;
|
||||
_searchResult = null;
|
||||
_error = null;
|
||||
}
|
||||
|
||||
// Search on Enter key
|
||||
if (e.Key == "Enter" && !string.IsNullOrWhiteSpace(_clubName))
|
||||
{
|
||||
await SearchClub();
|
||||
}
|
||||
}
|
||||
|
||||
private async Task SearchClub()
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(_clubName))
|
||||
return;
|
||||
|
||||
_isSearching = true;
|
||||
_error = null;
|
||||
_searched = false;
|
||||
_searchResult = null;
|
||||
|
||||
try
|
||||
{
|
||||
_searchResult = await ClubService.GetByNameAsync(_clubName.Trim());
|
||||
_searched = true;
|
||||
|
||||
// Check if user is already member
|
||||
if (_searchResult is not null && _currentUser is not null)
|
||||
{
|
||||
var existingMembership = _currentUser.ClubMemberships
|
||||
.FirstOrDefault(m => m.ClubId == _searchResult.Id);
|
||||
|
||||
if (existingMembership is not null)
|
||||
{
|
||||
_error = "Du bist bereits Mitglied dieses Clubs oder hast einen offenen Antrag.";
|
||||
_searchResult = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_error = $"Fehler bei der Suche: {ex.Message}";
|
||||
}
|
||||
finally
|
||||
{
|
||||
_isSearching = false;
|
||||
}
|
||||
}
|
||||
|
||||
private async Task SubmitRequest()
|
||||
{
|
||||
if (_searchResult is null || _currentUser is null)
|
||||
return;
|
||||
|
||||
_isSubmitting = true;
|
||||
_error = null;
|
||||
|
||||
try
|
||||
{
|
||||
var success = await UserService.RequestClubMembershipAsync(
|
||||
_currentUser.ProfileId,
|
||||
_searchResult.Id);
|
||||
|
||||
if (success)
|
||||
{
|
||||
_requestSent = true;
|
||||
Snackbar.Add("Beitrittsantrag erfolgreich gesendet", Severity.Success);
|
||||
}
|
||||
else
|
||||
{
|
||||
_error = "Der Antrag konnte nicht gesendet werden. Moeglicherweise existiert bereits ein Antrag.";
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_error = $"Fehler beim Senden des Antrags: {ex.Message}";
|
||||
}
|
||||
finally
|
||||
{
|
||||
_isSubmitting = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void ResetForm()
|
||||
{
|
||||
_clubName = "";
|
||||
_searchResult = null;
|
||||
_searched = false;
|
||||
_requestSent = false;
|
||||
_error = null;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,13 +1,16 @@
|
|||
@page "/dashboard"
|
||||
@attribute [Authorize(Policy = "ClubViewer")]
|
||||
@attribute [Authorize]
|
||||
|
||||
@using Koogle.Application.DTOs
|
||||
@using Koogle.Application.Interfaces
|
||||
@using Koogle.Domain.Enums
|
||||
@using Koogle.Infrastructure.Security
|
||||
@using Koogle.Web.Components.Shared
|
||||
@using Microsoft.AspNetCore.Authorization
|
||||
|
||||
@inject IDashboardService DashboardService
|
||||
@inject IUserService UserService
|
||||
@inject ICurrentClubContext CurrentClubContext
|
||||
@inject NavigationManager NavigationManager
|
||||
@inject ISnackbar Snackbar
|
||||
|
||||
|
|
@ -19,6 +22,21 @@
|
|||
{
|
||||
<MudProgressLinear Indeterminate="true" Color="Color.Primary" />
|
||||
}
|
||||
else if (_hasNoClub)
|
||||
{
|
||||
<MudPaper Class="pa-6" Elevation="2" MaxWidth="600px">
|
||||
<div class="d-flex flex-column align-center text-center">
|
||||
<MudIcon Icon="@Icons.Material.Filled.GroupOff" Size="Size.Large" Color="Color.Secondary" Class="mb-4" />
|
||||
<MudText Typo="Typo.h5" Class="mb-2">Keinem Club zugeordnet</MudText>
|
||||
<MudText Typo="Typo.body1" Color="Color.Secondary" Class="mb-4">
|
||||
Du bist noch keinem Club zugeordnet. Um Koogle zu nutzen, tritt einem bestehenden Club bei.
|
||||
</MudText>
|
||||
<MudButton Variant="Variant.Filled" Color="Color.Primary" Href="/account/join-club" StartIcon="@Icons.Material.Filled.GroupAdd">
|
||||
Einem Club beitreten
|
||||
</MudButton>
|
||||
</div>
|
||||
</MudPaper>
|
||||
}
|
||||
else if (_error is not null)
|
||||
{
|
||||
<MudAlert Severity="Severity.Error" Class="mb-4">@_error</MudAlert>
|
||||
|
|
@ -149,6 +167,7 @@ else if (_dashboard is not null)
|
|||
@code {
|
||||
private DashboardDto? _dashboard;
|
||||
private bool _isLoading = true;
|
||||
private bool _hasNoClub;
|
||||
private string? _error;
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
|
|
@ -162,6 +181,20 @@ else if (_dashboard is not null)
|
|||
{
|
||||
_isLoading = true;
|
||||
_error = null;
|
||||
|
||||
// Check if user has club context
|
||||
var clubId = CurrentClubContext.ClubId;
|
||||
if (clubId == Guid.Empty)
|
||||
{
|
||||
// Double-check via user service
|
||||
var user = await UserService.GetCurrentUserAsync();
|
||||
if (user == null || user.ClubMemberships.Count == 0)
|
||||
{
|
||||
_hasNoClub = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
_dashboard = await DashboardService.GetDashboardAsync();
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
|
|
|||
Loading…
Reference in New Issue