add profile page
This commit is contained in:
parent
ad3ac3185c
commit
d26a2cb1c5
|
|
@ -333,7 +333,7 @@ NavMenu.razor:
|
|||
| ✓ | B1 | User/Account | UserService erweitern | 1 Service, 1 Interface, 1 DTO |
|
||||
| ✓ | B2 | User/Account | Register Page | 1 Razor |
|
||||
| ✓ | B3 | User/Account | Password Reset Pages | 2 Razor |
|
||||
| ☐ | B4 | User/Account | Profile Page | 1 Razor |
|
||||
| ✓ | B4 | User/Account | Profile Page | 1 Razor |
|
||||
| ☐ | B5 | User/Account | Admin Users Page | 1 Razor |
|
||||
| ☐ | **C1** | **Clubs** | **ClubState Fluxor** | **4 State-Dateien** |
|
||||
| ☐ | **C2** | **Clubs** | **Club Pages - ERSTES TESTBARES MVP** | **1 Razor** |
|
||||
|
|
|
|||
|
|
@ -2,6 +2,9 @@
|
|||
|
||||
@inject IState<AuthState> AuthState
|
||||
@inject IDispatcher Dispatcher
|
||||
@inject Microsoft.AspNetCore.Antiforgery.IAntiforgery Antiforgery
|
||||
@inject IHttpContextAccessor HttpContextAccessor
|
||||
@inject IJSRuntime JS
|
||||
|
||||
<AuthStateInitializer />
|
||||
|
||||
|
|
@ -18,6 +21,18 @@
|
|||
<MudLayout>
|
||||
|
||||
<MudAppBar Elevation="1" Dense="true">
|
||||
<MudIconButton Icon="@Icons.Material.Filled.Menu" Color="Color.Inherit" Edge="Edge.Start" OnClick="ToggleDrawer" />
|
||||
<MudText Typo="Typo.h6">KOOGLE</MudText>
|
||||
<MudSpacer />
|
||||
@if (AuthState.Value.IsAuthenticated)
|
||||
{
|
||||
<MudMenu Icon="@Icons.Material.Filled.Person" Color="Color.Inherit" AnchorOrigin="Origin.BottomRight" TransformOrigin="Origin.TopRight">
|
||||
<MudMenuItem Href="/account/profile" Icon="@Icons.Material.Filled.AccountCircle">Profil</MudMenuItem>
|
||||
<MudDivider />
|
||||
<MudMenuItem OnClick="Logout" Icon="@Icons.Material.Filled.Logout">Abmelden</MudMenuItem>
|
||||
</MudMenu>
|
||||
}
|
||||
<MudIconButton Icon="@(_isDarkMode ? Icons.Material.Filled.LightMode : Icons.Material.Filled.DarkMode)" Color="Color.Inherit" OnClick="ToggleDarkMode" />
|
||||
</MudAppBar>
|
||||
|
||||
<MudDrawer @bind-Open="_drawerOpen"
|
||||
|
|
@ -51,12 +66,34 @@
|
|||
<span class="dismiss">🗙</span>
|
||||
</div>
|
||||
|
||||
<!-- Hidden logout form -->
|
||||
<form id="logout-form" method="post" action="/auth/logout" style="display:none;">
|
||||
<input type="hidden" name="__RequestVerificationToken" value="@_logoutToken" />
|
||||
<input type="hidden" name="returnUrl" value="/account/login" />
|
||||
</form>
|
||||
|
||||
|
||||
@code
|
||||
{
|
||||
private bool _drawerOpen = true;
|
||||
|
||||
private bool _isDarkMode = false;
|
||||
private string _logoutToken = "";
|
||||
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
base.OnInitialized();
|
||||
var http = HttpContextAccessor.HttpContext;
|
||||
if (http != null)
|
||||
{
|
||||
var tokens = Antiforgery.GetAndStoreTokens(http);
|
||||
_logoutToken = tokens.RequestToken ?? "";
|
||||
}
|
||||
}
|
||||
|
||||
private async Task Logout()
|
||||
{
|
||||
await JS.InvokeVoidAsync("eval", "document.getElementById('logout-form').submit()");
|
||||
}
|
||||
|
||||
private readonly MudTheme _theme = new()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -0,0 +1,218 @@
|
|||
@page "/account/profile"
|
||||
@attribute [Authorize]
|
||||
|
||||
@using Fluxor
|
||||
@using Koogle.Application.DTOs
|
||||
@using Koogle.Application.Interfaces
|
||||
@using Koogle.Web.Store.AuthState
|
||||
@using Microsoft.AspNetCore.Authorization
|
||||
|
||||
@inject IState<AuthState> AuthState
|
||||
@inject IUserService UserService
|
||||
@inject ISnackbar Snackbar
|
||||
|
||||
@inherits Fluxor.Blazor.Web.Components.FluxorComponent
|
||||
|
||||
<PageTitle>Profil</PageTitle>
|
||||
|
||||
<MudContainer MaxWidth="MaxWidth.Small" Class="mt-4">
|
||||
<MudText Typo="Typo.h4" Class="mb-4">Mein Profil</MudText>
|
||||
|
||||
@if (_isLoading)
|
||||
{
|
||||
<MudProgressCircular Indeterminate="true" />
|
||||
}
|
||||
else if (_user == null)
|
||||
{
|
||||
<MudAlert Severity="Severity.Warning">Benutzer nicht gefunden.</MudAlert>
|
||||
}
|
||||
else
|
||||
{
|
||||
<MudPaper Class="pa-4 mb-4" Elevation="2">
|
||||
<MudText Typo="Typo.h6" Class="mb-3">Kontoinformationen</MudText>
|
||||
|
||||
<MudTextField @bind-Value="_displayName"
|
||||
Label="Anzeigename"
|
||||
Variant="Variant.Outlined"
|
||||
Class="mb-3" />
|
||||
|
||||
<MudTextField Value="@_user.Identity.Email"
|
||||
Label="E-Mail"
|
||||
Variant="Variant.Outlined"
|
||||
ReadOnly="true"
|
||||
Disabled="true"
|
||||
Class="mb-3" />
|
||||
|
||||
<MudSelect @bind-Value="_locale"
|
||||
Label="Sprache"
|
||||
Variant="Variant.Outlined"
|
||||
Class="mb-3">
|
||||
<MudSelectItem Value="@("de-DE")">Deutsch</MudSelectItem>
|
||||
<MudSelectItem Value="@("en-US")">English</MudSelectItem>
|
||||
</MudSelect>
|
||||
|
||||
<MudSelect @bind-Value="_timeZone"
|
||||
Label="Zeitzone"
|
||||
Variant="Variant.Outlined"
|
||||
Class="mb-4">
|
||||
<MudSelectItem Value="@("Europe/Berlin")">Europe/Berlin</MudSelectItem>
|
||||
<MudSelectItem Value="@("Europe/Vienna")">Europe/Vienna</MudSelectItem>
|
||||
<MudSelectItem Value="@("Europe/Zurich")">Europe/Zurich</MudSelectItem>
|
||||
<MudSelectItem Value="@("UTC")">UTC</MudSelectItem>
|
||||
</MudSelect>
|
||||
|
||||
<MudButton Variant="Variant.Filled"
|
||||
Color="Color.Primary"
|
||||
OnClick="SaveProfile"
|
||||
Disabled="_isSaving">
|
||||
@if (_isSaving)
|
||||
{
|
||||
<MudProgressCircular Size="Size.Small" Indeterminate="true" Class="mr-2" />
|
||||
}
|
||||
Speichern
|
||||
</MudButton>
|
||||
</MudPaper>
|
||||
|
||||
<MudPaper Class="pa-4 mb-4" Elevation="2">
|
||||
<MudText Typo="Typo.h6" Class="mb-3">Club-Mitgliedschaften</MudText>
|
||||
|
||||
@if (_user.ClubMemberships.Count == 0)
|
||||
{
|
||||
<MudAlert Severity="Severity.Info">Keine Club-Mitgliedschaften vorhanden.</MudAlert>
|
||||
}
|
||||
else
|
||||
{
|
||||
<MudTable Items="_user.ClubMemberships" Dense="true" Hover="true">
|
||||
<HeaderContent>
|
||||
<MudTh>Club</MudTh>
|
||||
<MudTh>Rollen</MudTh>
|
||||
<MudTh>Standard</MudTh>
|
||||
</HeaderContent>
|
||||
<RowTemplate>
|
||||
<MudTd DataLabel="Club">@context.ClubName</MudTd>
|
||||
<MudTd DataLabel="Rollen">
|
||||
@foreach (var role in context.Roles)
|
||||
{
|
||||
<MudChip T="string" Size="Size.Small" Color="Color.Primary" Class="mr-1">@role</MudChip>
|
||||
}
|
||||
</MudTd>
|
||||
<MudTd DataLabel="Standard">
|
||||
@if (context.IsDefault)
|
||||
{
|
||||
<MudIcon Icon="@Icons.Material.Filled.Check" Color="Color.Success" />
|
||||
}
|
||||
else
|
||||
{
|
||||
<MudButton Size="Size.Small"
|
||||
Variant="Variant.Text"
|
||||
OnClick="@(() => SetDefaultClub(context.ClubId))"
|
||||
Disabled="_isSaving">
|
||||
Als Standard
|
||||
</MudButton>
|
||||
}
|
||||
</MudTd>
|
||||
</RowTemplate>
|
||||
</MudTable>
|
||||
}
|
||||
</MudPaper>
|
||||
|
||||
<MudPaper Class="pa-4" Elevation="2">
|
||||
<MudText Typo="Typo.h6" Class="mb-3">Sicherheit</MudText>
|
||||
<MudButton Href="/account/forgot-password"
|
||||
Variant="Variant.Outlined"
|
||||
Color="Color.Primary">
|
||||
Passwort aendern
|
||||
</MudButton>
|
||||
</MudPaper>
|
||||
}
|
||||
</MudContainer>
|
||||
|
||||
@code {
|
||||
private UserDto? _user;
|
||||
private string _displayName = "";
|
||||
private string _locale = "de-DE";
|
||||
private string _timeZone = "Europe/Berlin";
|
||||
private bool _isLoading = true;
|
||||
private bool _isSaving;
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
await base.OnInitializedAsync();
|
||||
await LoadUser();
|
||||
}
|
||||
|
||||
private async Task LoadUser()
|
||||
{
|
||||
_isLoading = true;
|
||||
try
|
||||
{
|
||||
_user = await UserService.GetCurrentUserAsync();
|
||||
if (_user != null)
|
||||
{
|
||||
_displayName = _user.DisplayName;
|
||||
_locale = _user.Locale ?? "de-DE";
|
||||
_timeZone = _user.TimeZone ?? "Europe/Berlin";
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
_isLoading = false;
|
||||
}
|
||||
}
|
||||
|
||||
private async Task SaveProfile()
|
||||
{
|
||||
_isSaving = true;
|
||||
try
|
||||
{
|
||||
var dto = new UpdateUserProfileDto
|
||||
{
|
||||
DisplayName = _displayName,
|
||||
Locale = _locale,
|
||||
TimeZone = _timeZone
|
||||
};
|
||||
|
||||
var result = await UserService.UpdateProfileAsync(dto);
|
||||
if (result != null)
|
||||
{
|
||||
_user = result;
|
||||
Snackbar.Add("Profil gespeichert", Severity.Success);
|
||||
}
|
||||
else
|
||||
{
|
||||
Snackbar.Add("Fehler beim Speichern", Severity.Error);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
_isSaving = false;
|
||||
}
|
||||
}
|
||||
|
||||
private async Task SetDefaultClub(Guid clubId)
|
||||
{
|
||||
_isSaving = true;
|
||||
try
|
||||
{
|
||||
var dto = new UpdateUserProfileDto
|
||||
{
|
||||
DefaultClubId = clubId
|
||||
};
|
||||
|
||||
var result = await UserService.UpdateProfileAsync(dto);
|
||||
if (result != null)
|
||||
{
|
||||
_user = result;
|
||||
Snackbar.Add("Standard-Club geaendert", Severity.Success);
|
||||
}
|
||||
else
|
||||
{
|
||||
Snackbar.Add("Fehler beim Aendern", Severity.Error);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
_isSaving = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue