OnProfNext/OnProfNext.Client/Pages/Users.razor
2025-10-15 15:01:00 +02:00

275 lines
8.5 KiB
Plaintext

@page "/users"
@using OnProfNext.Client.Services
@using OnProfNext.Shared.Models
@using OnProfNext.Shared.Models.DTOs
@inject UserApiService UserService
@inject AuthService AuthService
@inject NavigationManager Nav
<h3 class="mb-3">Benutzerübersicht</h3>
@if (errorMessage is not null)
{
<div class="alert alert-danger">@errorMessage</div>
}
else if (users is null)
{
<p><em>Lade Daten...</em></p>
}
else if (!users.Any())
{
<p>Keine Benutzer gefunden.</p>
}
else
{
<table class="table table-striped">
<thead>
<tr>
<th>Username</th>
<th>Vorname</th>
<th>Nachname</th>
<th>E-Mail</th>
<th>Mandant</th>
</tr>
</thead>
<tbody>
@foreach (var u in users)
{
<tr class="user-row" @onclick="() => OpenUserDetail(u.Id)">
<td>@u.Username</td>
<td>@u.FirstName</td>
<td>@u.LastName</td>
<td>@u.Email</td>
<td>@u.MandantId</td>
</tr>
}
</tbody>
</table>
}
@if (selectedUser is not null)
{
<div class="modal fade show d-block" tabindex="-1" style="background-color: rgba(0,0,0,0.5);">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Benutzer bearbeiten</h5>
<button type="button" class="btn-close" @onclick="CloseModal"></button>
</div>
<div class="modal-body">
<EditForm Model="selectedUser" OnValidSubmit="UpdateUserAsync">
<DataAnnotationsValidator />
<div class="mb-3">
<label>Vorname</label>
<InputText class="form-control" @bind-Value="selectedUser.FirstName" />
</div>
<div class="mb-3">
<label>Nachname</label>
<InputText class="form-control" @bind-Value="selectedUser.LastName" />
</div>
<div class="mb-3">
<label>E-Mail</label>
<InputText class="form-control" @bind-Value="selectedUser.Email" />
</div>
<div class="mb-3">
<label>Mandant</label>
<InputNumber class="form-control" @bind-Value="selectedUser.MandantId" />
</div>
<div class="form-check">
<InputCheckbox class="form-check-input" @bind-Value="selectedUser.IsActive" />
<label class="form-check-label">Aktiv</label>
</div>
<div class="modal-footer mt-3 d-flex justify-content-between">
<button type="button" class="btn btn-secondary" @onclick="CloseModal">Abbrechen</button>
<div>
<button type="submit" class="btn btn-primary me-2">Speichern</button>
<button type="button" class="btn btn-outline-danger" @onclick="ShowDeleteConfirm">Löschen</button>
</div>
</div>
</EditForm>
</div>
</div>
</div>
</div>
}
@if (showDeleteConfirm && selectedUser is not null)
{
<div class="modal fade show d-block" tabindex="-1" style="background-color: rgba(0,0,0,0.6);">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content">
<div class="modal-header bg-danger text-white">
<h5 class="modal-title">Benutzer löschen</h5>
<button type="button" class="btn-close btn-close-white" @onclick="CloseDeleteConfirm"></button>
</div>
<div class="modal-body">
<p>
⚠️ Bist du sicher, dass du den Benutzer
<strong>@selectedUser.Username</strong> löschen möchtest?<br />
Dies kann <strong>nicht rückgängig gemacht</strong> werden.
</p>
<div class="mb-3">
<label class="form-label">Zur Bestätigung den Benutzernamen eingeben:</label>
<InputText class="form-control"
@bind-Value="deleteConfirmInput"
oninput="@((ChangeEventArgs e) => OnDeleteConfirmInputChanged(e))" />
</div>
</div>
<div class="modal-footer">
<button class="btn btn-secondary" @onclick="CloseDeleteConfirm">Abbrechen</button>
<button class="btn"
style="@($"background-color: {(IsDeleteConfirmed ? "#dc3545" : "#f5c6cb")}; color: white;")"
disabled="@(IsDeleteConfirmed ? null : true)"
@onclick="ConfirmDeleteUser">
@(IsDeleteConfirmed ? "Endgültig löschen" : "Löschen")
</button>
</div>
</div>
</div>
</div>
}
@code {
private List<UserDto>? users;
private string? errorMessage;
private UserDto? selectedUser;
private bool showDeleteConfirm = false;
private string deleteConfirmInput = string.Empty;
private bool IsDeleteConfirmed => selectedUser is not null && deleteConfirmInput == selectedUser.Username;
protected override async Task OnInitializedAsync()
{
var isLoggedIn = await AuthService.IsLoggedInAsync();
if (!isLoggedIn)
{
Nav.NavigateTo("/login", forceLoad: true);
return;
}
var result = await UserService.GetUsersAsync();
if (!result.Success)
{
errorMessage = result.Error;
return;
}
users = result.Data;
}
private void OpenUserDetail(int id)
{
selectedUser = users?.FirstOrDefault(u => u.Id == id);
}
private void CloseModal()
{
selectedUser = null;
showDeleteConfirm = false;
deleteConfirmInput = string.Empty;
}
private void OnDeleteConfirmInputChanged(ChangeEventArgs e)
{
deleteConfirmInput = e.Value?.ToString() ?? string.Empty;
StateHasChanged();
}
private void ShowDeleteConfirm()
{
showDeleteConfirm = true;
deleteConfirmInput = string.Empty;
}
private void CloseDeleteConfirm()
{
showDeleteConfirm = false;
deleteConfirmInput = string.Empty;
}
//Delete Action
private async Task ConfirmDeleteUser()
{
if(selectedUser is null)
{
return;
}
var result = await UserService.DeleteUserAsync(selectedUser.Id);
if(!result.Success)
{
errorMessage = result.Error;
return;
}
users?.Remove(selectedUser);
CloseModal();
StateHasChanged();
}
private async Task UpdateUserAsync()
{
if(selectedUser is null)
{
return;
}
var result = await UserService.UpdateUserAsync(selectedUser);
if(!result.Success)
{
errorMessage = result.Error;
return;
}
//Modal schließen und Liste aktualisieren
CloseModal();
var updated = await UserService.GetUsersAsync();
users = updated.Data;
StateHasChanged();
}
}
<style>
tr.user-row {
transition: all 0.2s ease-in-out;
cursor: pointer;
}
tr.user-row:hover {
transform: scale(1.01);
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
background-color: #f8f9fa;
}
.modal-backdrop {
background-color: rgba(0, 0, 0, 0.6);
}
.modal-content {
border-radius: 0.75rem;
}
.btn-outline-danger:hover {
background-color: #dc3545;
color: #fff;
}
</style>