@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 *@ Timetracker Freischaltung 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 { @* ── Tab Navigation ── *@ Anmelden @(_tenantInfo.IsTenant ? "Registrieren" : "Firma registrieren") @if (_activeTab == 0) { @* ── Login Form ── *@ @if (_error != null) { @_error } @if (_loading) { } Anmelden } else { @if (_tenantInfo.IsTenant) { @* ── Employee Register Form ── *@ @if (_error != null) { @_error } Ich akzeptiere die AGB. @if (_loading) { } Konto erstellen } else { @* ── Firm Register Form ── *@ @if (_error != null) { @_error } Administrator-Konto Ich akzeptiere die AGB. @if (_loading) { } Firma registrieren } } }
} @code { private TenantInfo? _tenantInfo; private int _activeTab = 0; private string? _error; private bool _loading; private string _honeypot = ""; private bool _acceptAgb; private bool _firmRegisteredSuccessfully; 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() { 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 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; } = ""; } }