Init
This commit is contained in:
71
OnProfNext.Client/Pages/CreateUser.razor
Normal file
71
OnProfNext.Client/Pages/CreateUser.razor
Normal file
@@ -0,0 +1,71 @@
|
||||
@page "/createuser"
|
||||
@using OnProfNext.Client.Services
|
||||
@using OnProfNext.Shared.Models
|
||||
@inject UserApiService UserService
|
||||
@inject NavigationManager Nav
|
||||
|
||||
<h3>Neuen Benutzer anlegen</h3>
|
||||
|
||||
|
||||
@if (errorMessage is not null)
|
||||
{
|
||||
<div class="alert alert-danger alert-dismissible fade show" role="alert">
|
||||
<strong>Fehler:</strong> @errorMessage
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
||||
</div>
|
||||
}
|
||||
|
||||
|
||||
<EditForm Model="newUser" OnValidSubmit="HandleValidSubmit">
|
||||
<DataAnnotationsValidator />
|
||||
<ValidationSummary />
|
||||
|
||||
<div class="mb-3">
|
||||
<label>Username</label>
|
||||
<InputText class="form-control" @bind-Value="newUser.Username" />
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label>E-Mail</label>
|
||||
<InputText class="form-control" @bind-Value="newUser.Email" />
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label>Passwort</label>
|
||||
<InputText type="password" class="form-control" @bind-Value="newUser.PasswordHash" />
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label>Vorname</label>
|
||||
<InputText class="form-control" @bind-Value="newUser.FirstName" />
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label>Nachname</label>
|
||||
<InputText class="form-control" @bind-Value="newUser.LastName" />
|
||||
</div>
|
||||
|
||||
<button class="btn btn-primary" type="submit">Speichern</button>
|
||||
</EditForm>
|
||||
|
||||
@code {
|
||||
private User newUser = new();
|
||||
private string? errorMessage;
|
||||
|
||||
private async Task HandleValidSubmit()
|
||||
{
|
||||
var result = await UserService.CreateUserAsync(newUser);
|
||||
|
||||
if(!result.Success)
|
||||
{
|
||||
errorMessage = result.Error;
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
Nav.NavigateTo("/users");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
7
OnProfNext.Client/Pages/Home.razor
Normal file
7
OnProfNext.Client/Pages/Home.razor
Normal file
@@ -0,0 +1,7 @@
|
||||
@page "/"
|
||||
|
||||
<PageTitle>Home</PageTitle>
|
||||
|
||||
<h1>Hello, world!</h1>
|
||||
|
||||
Welcome to your new app.
|
||||
263
OnProfNext.Client/Pages/Users.razor
Normal file
263
OnProfNext.Client/Pages/Users.razor
Normal file
@@ -0,0 +1,263 @@
|
||||
@page "/users"
|
||||
@using OnProfNext.Client.Services
|
||||
@using OnProfNext.Shared.Models
|
||||
@inject UserApiService UserService
|
||||
|
||||
<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<User>? users;
|
||||
private string? errorMessage;
|
||||
private User? 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 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>
|
||||
Reference in New Issue
Block a user