Init
This commit is contained in:
commit
6bcf3e881b
12
OnProfNext.Client/App.razor
Normal file
12
OnProfNext.Client/App.razor
Normal file
@ -0,0 +1,12 @@
|
||||
<Router AppAssembly="@typeof(App).Assembly">
|
||||
<Found Context="routeData">
|
||||
<RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" />
|
||||
<FocusOnNavigate RouteData="@routeData" Selector="h1" />
|
||||
</Found>
|
||||
<NotFound>
|
||||
<PageTitle>Not found</PageTitle>
|
||||
<LayoutView Layout="@typeof(MainLayout)">
|
||||
<p role="alert">Sorry, there's nothing at this address.</p>
|
||||
</LayoutView>
|
||||
</NotFound>
|
||||
</Router>
|
||||
16
OnProfNext.Client/Layout/MainLayout.razor
Normal file
16
OnProfNext.Client/Layout/MainLayout.razor
Normal file
@ -0,0 +1,16 @@
|
||||
@inherits LayoutComponentBase
|
||||
<div class="page">
|
||||
<div class="sidebar">
|
||||
<NavMenu />
|
||||
</div>
|
||||
|
||||
<main>
|
||||
<div class="top-row px-4">
|
||||
<a href="https://learn.microsoft.com/aspnet/core/" target="_blank">About</a>
|
||||
</div>
|
||||
|
||||
<article class="content px-4">
|
||||
@Body
|
||||
</article>
|
||||
</main>
|
||||
</div>
|
||||
77
OnProfNext.Client/Layout/MainLayout.razor.css
Normal file
77
OnProfNext.Client/Layout/MainLayout.razor.css
Normal file
@ -0,0 +1,77 @@
|
||||
.page {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
main {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.sidebar {
|
||||
background-image: linear-gradient(180deg, rgb(5, 39, 103) 0%, #3a0647 70%);
|
||||
}
|
||||
|
||||
.top-row {
|
||||
background-color: #f7f7f7;
|
||||
border-bottom: 1px solid #d6d5d5;
|
||||
justify-content: flex-end;
|
||||
height: 3.5rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.top-row ::deep a, .top-row ::deep .btn-link {
|
||||
white-space: nowrap;
|
||||
margin-left: 1.5rem;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.top-row ::deep a:hover, .top-row ::deep .btn-link:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.top-row ::deep a:first-child {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
@media (max-width: 640.98px) {
|
||||
.top-row {
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.top-row ::deep a, .top-row ::deep .btn-link {
|
||||
margin-left: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 641px) {
|
||||
.page {
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.sidebar {
|
||||
width: 250px;
|
||||
height: 100vh;
|
||||
position: sticky;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
.top-row {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.top-row.auth ::deep a:first-child {
|
||||
flex: 1;
|
||||
text-align: right;
|
||||
width: 0;
|
||||
}
|
||||
|
||||
.top-row, article {
|
||||
padding-left: 2rem !important;
|
||||
padding-right: 1.5rem !important;
|
||||
}
|
||||
}
|
||||
29
OnProfNext.Client/Layout/NavMenu.razor
Normal file
29
OnProfNext.Client/Layout/NavMenu.razor
Normal file
@ -0,0 +1,29 @@
|
||||
<div class="top-row ps-3 navbar navbar-dark">
|
||||
<div class="container-fluid">
|
||||
<a class="navbar-brand" href="">OnProfNext.Client</a>
|
||||
<button title="Navigation menu" class="navbar-toggler" @onclick="ToggleNavMenu">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="@NavMenuCssClass nav-scrollable" @onclick="ToggleNavMenu">
|
||||
<nav class="nav flex-column">
|
||||
<div class="nav-item px-3">
|
||||
<NavLink class="nav-link" href="" Match="NavLinkMatch.All">
|
||||
<span class="bi bi-house-door-fill-nav-menu" aria-hidden="true"></span> Home
|
||||
</NavLink>
|
||||
</div>
|
||||
</nav>
|
||||
</div>
|
||||
|
||||
@code {
|
||||
private bool collapseNavMenu = true;
|
||||
|
||||
private string? NavMenuCssClass => collapseNavMenu ? "collapse" : null;
|
||||
|
||||
private void ToggleNavMenu()
|
||||
{
|
||||
collapseNavMenu = !collapseNavMenu;
|
||||
}
|
||||
}
|
||||
83
OnProfNext.Client/Layout/NavMenu.razor.css
Normal file
83
OnProfNext.Client/Layout/NavMenu.razor.css
Normal file
@ -0,0 +1,83 @@
|
||||
.navbar-toggler {
|
||||
background-color: rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
|
||||
.top-row {
|
||||
min-height: 3.5rem;
|
||||
background-color: rgba(0,0,0,0.4);
|
||||
}
|
||||
|
||||
.navbar-brand {
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
|
||||
.bi {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
width: 1.25rem;
|
||||
height: 1.25rem;
|
||||
margin-right: 0.75rem;
|
||||
top: -1px;
|
||||
background-size: cover;
|
||||
}
|
||||
|
||||
.bi-house-door-fill-nav-menu {
|
||||
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='white' class='bi bi-house-door-fill' viewBox='0 0 16 16'%3E%3Cpath d='M6.5 14.5v-3.505c0-.245.25-.495.5-.495h2c.25 0 .5.25.5.5v3.5a.5.5 0 0 0 .5.5h4a.5.5 0 0 0 .5-.5v-7a.5.5 0 0 0-.146-.354L13 5.793V2.5a.5.5 0 0 0-.5-.5h-1a.5.5 0 0 0-.5.5v1.293L8.354 1.146a.5.5 0 0 0-.708 0l-6 6A.5.5 0 0 0 1.5 7.5v7a.5.5 0 0 0 .5.5h4a.5.5 0 0 0 .5-.5Z'/%3E%3C/svg%3E");
|
||||
}
|
||||
|
||||
.bi-plus-square-fill-nav-menu {
|
||||
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='white' class='bi bi-plus-square-fill' viewBox='0 0 16 16'%3E%3Cpath d='M2 0a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V2a2 2 0 0 0-2-2H2zm6.5 4.5v3h3a.5.5 0 0 1 0 1h-3v3a.5.5 0 0 1-1 0v-3h-3a.5.5 0 0 1 0-1h3v-3a.5.5 0 0 1 1 0z'/%3E%3C/svg%3E");
|
||||
}
|
||||
|
||||
.bi-list-nested-nav-menu {
|
||||
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='white' class='bi bi-list-nested' viewBox='0 0 16 16'%3E%3Cpath fill-rule='evenodd' d='M4.5 11.5A.5.5 0 0 1 5 11h10a.5.5 0 0 1 0 1H5a.5.5 0 0 1-.5-.5zm-2-4A.5.5 0 0 1 3 7h10a.5.5 0 0 1 0 1H3a.5.5 0 0 1-.5-.5zm-2-4A.5.5 0 0 1 1 3h10a.5.5 0 0 1 0 1H1a.5.5 0 0 1-.5-.5z'/%3E%3C/svg%3E");
|
||||
}
|
||||
|
||||
.nav-item {
|
||||
font-size: 0.9rem;
|
||||
padding-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.nav-item:first-of-type {
|
||||
padding-top: 1rem;
|
||||
}
|
||||
|
||||
.nav-item:last-of-type {
|
||||
padding-bottom: 1rem;
|
||||
}
|
||||
|
||||
.nav-item ::deep a {
|
||||
color: #d7d7d7;
|
||||
border-radius: 4px;
|
||||
height: 3rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
line-height: 3rem;
|
||||
}
|
||||
|
||||
.nav-item ::deep a.active {
|
||||
background-color: rgba(255,255,255,0.37);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.nav-item ::deep a:hover {
|
||||
background-color: rgba(255,255,255,0.1);
|
||||
color: white;
|
||||
}
|
||||
|
||||
@media (min-width: 641px) {
|
||||
.navbar-toggler {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.collapse {
|
||||
/* Never collapse the sidebar for wide screens */
|
||||
display: block;
|
||||
}
|
||||
|
||||
.nav-scrollable {
|
||||
/* Allow sidebar to scroll for tall menus */
|
||||
height: calc(100vh - 3.5rem);
|
||||
overflow-y: auto;
|
||||
}
|
||||
}
|
||||
19
OnProfNext.Client/OnProfNext.Client.csproj
Normal file
19
OnProfNext.Client/OnProfNext.Client.csproj
Normal file
@ -0,0 +1,19 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.BlazorWebAssembly">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="9.0.9" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="9.0.9" PrivateAssets="all" />
|
||||
<PackageReference Include="Microsoft.Extensions.Http" Version="9.0.9" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\OnProfNext.Shared\OnProfNext.Shared.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
6
OnProfNext.Client/OnProfNext.Client.csproj.user
Normal file
6
OnProfNext.Client/OnProfNext.Client.csproj.user
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<ActiveDebugProfile>https</ActiveDebugProfile>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
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>
|
||||
19
OnProfNext.Client/Program.cs
Normal file
19
OnProfNext.Client/Program.cs
Normal file
@ -0,0 +1,19 @@
|
||||
using Microsoft.AspNetCore.Components.Web;
|
||||
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
|
||||
using OnProfNext.Client;
|
||||
using OnProfNext.Client.Services;
|
||||
using Microsoft.Extensions.Http;
|
||||
using System.Net.Http;
|
||||
|
||||
var builder = WebAssemblyHostBuilder.CreateDefault(args);
|
||||
builder.RootComponents.Add<App>("#app");
|
||||
builder.RootComponents.Add<HeadOutlet>("head::after");
|
||||
|
||||
builder.Services.AddScoped<UserApiService>();
|
||||
|
||||
builder.Services.AddHttpClient<UserApiService>(client =>
|
||||
{
|
||||
client.BaseAddress = new Uri("https://localhost:7271/");
|
||||
});
|
||||
|
||||
await builder.Build().RunAsync();
|
||||
25
OnProfNext.Client/Properties/launchSettings.json
Normal file
25
OnProfNext.Client/Properties/launchSettings.json
Normal file
@ -0,0 +1,25 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/launchsettings.json",
|
||||
"profiles": {
|
||||
"http": {
|
||||
"commandName": "Project",
|
||||
"dotnetRunMessages": true,
|
||||
"launchBrowser": true,
|
||||
"inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}",
|
||||
"applicationUrl": "http://localhost:5223",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
},
|
||||
"https": {
|
||||
"commandName": "Project",
|
||||
"dotnetRunMessages": true,
|
||||
"launchBrowser": true,
|
||||
"inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}",
|
||||
"applicationUrl": "https://localhost:7082;http://localhost:5223",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
95
OnProfNext.Client/Services/UserApiService.cs
Normal file
95
OnProfNext.Client/Services/UserApiService.cs
Normal file
@ -0,0 +1,95 @@
|
||||
using OnProfNext.Shared.Models;
|
||||
using System.Net.Http.Json;
|
||||
|
||||
namespace OnProfNext.Client.Services
|
||||
{
|
||||
public class UserApiService
|
||||
{
|
||||
private readonly HttpClient _httpClient;
|
||||
|
||||
public UserApiService(HttpClient httpClient)
|
||||
{
|
||||
_httpClient = httpClient;
|
||||
}
|
||||
|
||||
public async Task<(bool Success, List<User>? Data, string? Error)> GetUsersAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
var users = await _httpClient.GetFromJsonAsync<List<User>>("api/users");
|
||||
return (true, users ?? new List<User>(), null);
|
||||
}
|
||||
catch (HttpRequestException ex)
|
||||
{
|
||||
return (false, null, "Keine Verbindung zum Server. Bitte später erneut versuchen.");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return(false, null, $"Unerwarteter Fehler: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<(bool Success, string? Error)> CreateUserAsync(User user)
|
||||
{
|
||||
try
|
||||
{
|
||||
var response = await _httpClient.PostAsJsonAsync("api/users", user);
|
||||
if (!response.IsSuccessStatusCode)
|
||||
{
|
||||
return (false, $"Fehler beim Anlegen: {response.ReasonPhrase}");
|
||||
}
|
||||
|
||||
return (true, null);
|
||||
}
|
||||
catch (HttpRequestException)
|
||||
{
|
||||
return (false, "Server nicht erreichbar.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public async Task<(bool Success, string? Error)> UpdateUserAsync(User user)
|
||||
{
|
||||
try
|
||||
{
|
||||
var response = await _httpClient.PutAsJsonAsync($"api/users/{user.Id}", user);
|
||||
|
||||
if(!response.IsSuccessStatusCode)
|
||||
{
|
||||
return (false, $"Fehler beim Aktualisieren: {response.ReasonPhrase}");
|
||||
}
|
||||
return (true, null);
|
||||
}
|
||||
|
||||
catch (HttpRequestException)
|
||||
{
|
||||
return (false, "Server nicht erreichbar.");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return (false, ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<(bool Success, string? Error)> DeleteUserAsync(int userId)
|
||||
{
|
||||
try
|
||||
{
|
||||
var response = await _httpClient.DeleteAsync($"api/users/{userId}");
|
||||
if (!response.IsSuccessStatusCode)
|
||||
{
|
||||
return (false, $"Fehler beim Löschen: {response.ReasonPhrase}");
|
||||
}
|
||||
return (true, null);
|
||||
}
|
||||
catch (HttpRequestException)
|
||||
{
|
||||
return (false, "Server nicht erreichbar.");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return (false, ex.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
10
OnProfNext.Client/_Imports.razor
Normal file
10
OnProfNext.Client/_Imports.razor
Normal file
@ -0,0 +1,10 @@
|
||||
@using System.Net.Http
|
||||
@using System.Net.Http.Json
|
||||
@using Microsoft.AspNetCore.Components.Forms
|
||||
@using Microsoft.AspNetCore.Components.Routing
|
||||
@using Microsoft.AspNetCore.Components.Web
|
||||
@using Microsoft.AspNetCore.Components.Web.Virtualization
|
||||
@using Microsoft.AspNetCore.Components.WebAssembly.Http
|
||||
@using Microsoft.JSInterop
|
||||
@using OnProfNext.Client
|
||||
@using OnProfNext.Client.Layout
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
OnProfNext.Client/bin/Debug/net9.0/Microsoft.CSharp.dll
Normal file
BIN
OnProfNext.Client/bin/Debug/net9.0/Microsoft.CSharp.dll
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
OnProfNext.Client/bin/Debug/net9.0/Microsoft.Extensions.Http.dll
Normal file
BIN
OnProfNext.Client/bin/Debug/net9.0/Microsoft.Extensions.Http.dll
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
OnProfNext.Client/bin/Debug/net9.0/Microsoft.JSInterop.dll
Normal file
BIN
OnProfNext.Client/bin/Debug/net9.0/Microsoft.JSInterop.dll
Normal file
Binary file not shown.
Binary file not shown.
BIN
OnProfNext.Client/bin/Debug/net9.0/Microsoft.VisualBasic.dll
Normal file
BIN
OnProfNext.Client/bin/Debug/net9.0/Microsoft.VisualBasic.dll
Normal file
Binary file not shown.
Binary file not shown.
BIN
OnProfNext.Client/bin/Debug/net9.0/Microsoft.Win32.Registry.dll
Normal file
BIN
OnProfNext.Client/bin/Debug/net9.0/Microsoft.Win32.Registry.dll
Normal file
Binary file not shown.
BIN
OnProfNext.Client/bin/Debug/net9.0/OnProfNext.Client.dll
Normal file
BIN
OnProfNext.Client/bin/Debug/net9.0/OnProfNext.Client.dll
Normal file
Binary file not shown.
BIN
OnProfNext.Client/bin/Debug/net9.0/OnProfNext.Client.pdb
Normal file
BIN
OnProfNext.Client/bin/Debug/net9.0/OnProfNext.Client.pdb
Normal file
Binary file not shown.
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
BIN
OnProfNext.Client/bin/Debug/net9.0/OnProfNext.Shared.dll
Normal file
BIN
OnProfNext.Client/bin/Debug/net9.0/OnProfNext.Shared.dll
Normal file
Binary file not shown.
BIN
OnProfNext.Client/bin/Debug/net9.0/OnProfNext.Shared.pdb
Normal file
BIN
OnProfNext.Client/bin/Debug/net9.0/OnProfNext.Shared.pdb
Normal file
Binary file not shown.
BIN
OnProfNext.Client/bin/Debug/net9.0/System.AppContext.dll
Normal file
BIN
OnProfNext.Client/bin/Debug/net9.0/System.AppContext.dll
Normal file
Binary file not shown.
BIN
OnProfNext.Client/bin/Debug/net9.0/System.Buffers.dll
Normal file
BIN
OnProfNext.Client/bin/Debug/net9.0/System.Buffers.dll
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
OnProfNext.Client/bin/Debug/net9.0/System.Collections.dll
Normal file
BIN
OnProfNext.Client/bin/Debug/net9.0/System.Collections.dll
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
OnProfNext.Client/bin/Debug/net9.0/System.ComponentModel.dll
Normal file
BIN
OnProfNext.Client/bin/Debug/net9.0/System.ComponentModel.dll
Normal file
Binary file not shown.
BIN
OnProfNext.Client/bin/Debug/net9.0/System.Configuration.dll
Normal file
BIN
OnProfNext.Client/bin/Debug/net9.0/System.Configuration.dll
Normal file
Binary file not shown.
BIN
OnProfNext.Client/bin/Debug/net9.0/System.Console.dll
Normal file
BIN
OnProfNext.Client/bin/Debug/net9.0/System.Console.dll
Normal file
Binary file not shown.
BIN
OnProfNext.Client/bin/Debug/net9.0/System.Core.dll
Normal file
BIN
OnProfNext.Client/bin/Debug/net9.0/System.Core.dll
Normal file
Binary file not shown.
BIN
OnProfNext.Client/bin/Debug/net9.0/System.Data.Common.dll
Normal file
BIN
OnProfNext.Client/bin/Debug/net9.0/System.Data.Common.dll
Normal file
Binary file not shown.
Binary file not shown.
BIN
OnProfNext.Client/bin/Debug/net9.0/System.Data.dll
Normal file
BIN
OnProfNext.Client/bin/Debug/net9.0/System.Data.dll
Normal file
Binary file not shown.
Binary file not shown.
BIN
OnProfNext.Client/bin/Debug/net9.0/System.Diagnostics.Debug.dll
Normal file
BIN
OnProfNext.Client/bin/Debug/net9.0/System.Diagnostics.Debug.dll
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
OnProfNext.Client/bin/Debug/net9.0/System.Diagnostics.Tools.dll
Normal file
BIN
OnProfNext.Client/bin/Debug/net9.0/System.Diagnostics.Tools.dll
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
OnProfNext.Client/bin/Debug/net9.0/System.Drawing.Primitives.dll
Normal file
BIN
OnProfNext.Client/bin/Debug/net9.0/System.Drawing.Primitives.dll
Normal file
Binary file not shown.
BIN
OnProfNext.Client/bin/Debug/net9.0/System.Drawing.dll
Normal file
BIN
OnProfNext.Client/bin/Debug/net9.0/System.Drawing.dll
Normal file
Binary file not shown.
BIN
OnProfNext.Client/bin/Debug/net9.0/System.Dynamic.Runtime.dll
Normal file
BIN
OnProfNext.Client/bin/Debug/net9.0/System.Dynamic.Runtime.dll
Normal file
Binary file not shown.
BIN
OnProfNext.Client/bin/Debug/net9.0/System.Formats.Asn1.dll
Normal file
BIN
OnProfNext.Client/bin/Debug/net9.0/System.Formats.Asn1.dll
Normal file
Binary file not shown.
BIN
OnProfNext.Client/bin/Debug/net9.0/System.Formats.Tar.dll
Normal file
BIN
OnProfNext.Client/bin/Debug/net9.0/System.Formats.Tar.dll
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
OnProfNext.Client/bin/Debug/net9.0/System.Globalization.dll
Normal file
BIN
OnProfNext.Client/bin/Debug/net9.0/System.Globalization.dll
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
OnProfNext.Client/bin/Debug/net9.0/System.IO.Compression.dll
Normal file
BIN
OnProfNext.Client/bin/Debug/net9.0/System.IO.Compression.dll
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
OnProfNext.Client/bin/Debug/net9.0/System.IO.FileSystem.dll
Normal file
BIN
OnProfNext.Client/bin/Debug/net9.0/System.IO.FileSystem.dll
Normal file
Binary file not shown.
BIN
OnProfNext.Client/bin/Debug/net9.0/System.IO.IsolatedStorage.dll
Normal file
BIN
OnProfNext.Client/bin/Debug/net9.0/System.IO.IsolatedStorage.dll
Normal file
Binary file not shown.
Binary file not shown.
BIN
OnProfNext.Client/bin/Debug/net9.0/System.IO.Pipelines.dll
Normal file
BIN
OnProfNext.Client/bin/Debug/net9.0/System.IO.Pipelines.dll
Normal file
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user