@page "/login"
@rendermode InteractiveWebAssembly
@attribute [AllowAnonymous]
@using System.Net.Http.Json
@inject IAuthService AuthService
@inject NavigationManager Nav
@inject IJSRuntime JSRuntime
@inject HttpClient Http
@GetPageTitle()
@if (TenantInfo == null)
{
@* Loading indicator while resolving Tenant *@
Lade Timetracker…
}
else if (TenantInfo.IsTenant && !TenantInfo.IsApproved)
{
@* Pending Approval Screen *@
TimetrackerFreischaltung ausstehend
Die Firma @TenantInfo.Name wurde erfolgreich registriert.
Der Zugang wird derzeit von unserem SuperAdmin geprüft und in Kürze freigeschaltet.
Bitte laden Sie diese Seite in Kürze neu, sobald Ihr Account freigegeben wurde.
}
else
{
@* Main login/registration container *@
@* ── Logo / Header ── *@
@(TenantInfo.IsTenant ? TenantInfo.Name : "Timetracker SaaS")
@if (!TenantInfo.IsTenant)
{
Zentrales Portal
}
@if (_firmRegisteredSuccessfully)
{
@* Success feedback after firm registration *@
Registrierung erfolgreich!
Ihre Firma @_firmModel.CompanyName wurde erfolgreich registriert.
Ihr Zugang muss nun durch den SuperAdmin freigegeben werden. Danach können Sie sich unter Ihrer Subdomain anmelden:
@GetTenantUrl()
Zurück zum Login
} else {
@* ── Header / Navigation ── *@
@if (_activeTab == 2)
{
@* ── Back Button for Firm Registration ── *@
Firma registrieren
}
else
{
@* ── Tab Navigation ── *@
Anmelden
Registrieren
}
@if (_activeTab == 0)
{
@* ── Login Form ── *@
@if (_error != null)
{
@_error
}
@if (_loading)
{
}
Anmelden
}
else if (_activeTab == 1)
{
@if (TenantInfo.IsTenant)
{
@* ── Employee Register Form ── *@
@if (_error != null)
{
@_error
}
Ich akzeptiere die AGB.
@if (_loading)
{
}
Konto erstellen
}
else
{
@* ── Single User Register Form ── *@
@if (_error != null)
{
@_error
}
Ich akzeptiere die AGB.
@if (_loading)
{
}
Konto erstellen
}
}
else if (_activeTab == 2)
{
@* ── Firm Register Form ── *@
@if (_error != null)
{
@_error
}
Administrator-KontoIch akzeptiere die AGB.
@if (_loading)
{
}
Firma registrieren
}
@if (!TenantInfo.IsTenant && _activeTab != 2)
{
Sie möchten Timetracker für Ihr Unternehmen nutzen?
Eigene Firma registrieren
}
}
}
@code {
[PersistentState(AllowUpdates = true)]
public TenantInfo? TenantInfo { get; set; }
private int _activeTab = 0;
private string? _error;
private bool _loading;
private string _honeypot = "";
private bool _acceptAgb;
private bool _firmRegisteredSuccessfully;
private string _confirmPassword = "";
private readonly AuthModel _loginModel = new();
private readonly AuthModel _registerModel = new();
private readonly FirmModel _firmModel = new();
[SupplyParameterFromQuery(Name = "error")]
public string? ErrorParam { get; set; }
[SupplyParameterFromQuery(Name = "tab")]
public string? TabParam { get; set; }
protected override async Task OnInitializedAsync()
{
if (TenantInfo is null)
{
try
{
TenantInfo = await Http.GetFromJsonAsync("api/tenant/current");
}
catch (Exception ex)
{
Console.WriteLine($"Fehler beim Abrufen der TenantInfo: {ex.Message}");
// Fallback
TenantInfo = new TenantInfo { IsTenant = false };
}
}
}
protected override void OnParametersSet()
{
_error = ErrorParam switch
{
"invalid" => "Benutzername oder Passwort falsch.",
not null => Uri.UnescapeDataString(ErrorParam),
_ => null
};
_activeTab = TabParam == "register" ? 1 : 0;
}
private void SetTab(int tab)
{
_activeTab = tab;
_error = null;
}
private string GetPageTitle()
{
if (TenantInfo == null) return "Lade…";
return TenantInfo.IsTenant ? $"Anmelden bei {TenantInfo.Name} – Timetracker" : "Anmelden – Timetracker SaaS";
}
private string GetDomainSuffix()
{
var uri = new Uri(Nav.BaseUri);
var host = uri.Host;
return $".{host}";
}
private string GetTenantUrl()
{
var uri = new Uri(Nav.BaseUri);
var scheme = uri.Scheme;
var port = uri.Port == 80 || uri.Port == 443 ? "" : $":{uri.Port}";
var host = uri.Host;
return $"{scheme}://{_firmModel.Subdomain.ToLower().Trim()}.{host}{port}";
}
private void ResetRegistrationFlow()
{
_firmRegisteredSuccessfully = false;
_activeTab = 0;
_error = null;
}
private async Task HandleLogin()
{
_loading = true;
_error = null;
try
{
var user = await AuthService.LoginAsync(_loginModel.Username, _loginModel.Password);
if (user != null)
{
Nav.NavigateTo("/", forceLoad: true);
}
else
{
_error = "Benutzername oder Passwort falsch.";
}
}
catch (Exception ex)
{
_error = $"Login Fehler: {ex.Message}";
}
finally
{
_loading = false;
}
}
private async Task HandleRegister()
{
if (!_acceptAgb)
{
_error = "Du musst die AGB akzeptieren.";
return;
}
_loading = true;
_error = null;
try
{
var (user, error) = await AuthService.RegisterAsync(_registerModel.Username, _registerModel.Password, _honeypot);
if (user != null)
{
await JSRuntime.InvokeVoidAsync("localStorage.setItem", "showOnboarding", "true");
Nav.NavigateTo("/", forceLoad: true);
}
else
{
_error = error ?? "Registrierung fehlgeschlagen.";
}
}
catch (Exception ex)
{
_error = $"Registrierungs Fehler: {ex.Message}";
}
finally
{
_loading = false;
}
}
private async Task HandleSingleUserRegister()
{
if (!_acceptAgb)
{
_error = "Du musst die AGB akzeptieren.";
return;
}
if (_registerModel.Password != _confirmPassword)
{
_error = "Passwörter stimmen nicht überein.";
return;
}
_loading = true;
_error = null;
try
{
var (user, error) = await AuthService.RegisterAsync(_registerModel.Username, _registerModel.Password, _honeypot);
if (user != null)
{
await JSRuntime.InvokeVoidAsync("localStorage.setItem", "showOnboarding", "true");
Nav.NavigateTo("/", forceLoad: true);
}
else
{
_error = error ?? "Registrierung fehlgeschlagen.";
}
}
catch (Exception ex)
{
_error = $"Registrierungs Fehler: {ex.Message}";
}
finally
{
_loading = false;
}
}
private async Task HandleRegisterFirm()
{
if (!_acceptAgb)
{
_error = "Du musst die AGB akzeptieren.";
return;
}
if (_firmModel.AdminPassword != _firmModel.ConfirmPassword)
{
_error = "Passwörter stimmen nicht überein.";
return;
}
_loading = true;
_error = null;
try
{
var req = new RegisterFirmRequest(
_firmModel.CompanyName,
_firmModel.Subdomain,
_firmModel.AdminUsername,
_firmModel.AdminPassword
);
var (tenant, error) = await AuthService.RegisterFirmAsync(req);
if (tenant != null)
{
_firmRegisteredSuccessfully = true;
}
else
{
_error = error ?? "Registrierung der Firma fehlgeschlagen.";
}
}
catch (Exception ex)
{
_error = $"Registrierungs Fehler: {ex.Message}";
}
finally
{
_loading = false;
}
}
private class AuthModel
{
public string Username { get; set; } = "";
public string Password { get; set; } = "";
}
private class FirmModel
{
public string CompanyName { get; set; } = "";
public string Subdomain { get; set; } = "";
public string AdminUsername { get; set; } = "";
public string AdminPassword { get; set; } = "";
public string ConfirmPassword { get; set; } = "";
}
}