Files
timetracker/timetracker.Client/Components/Layout/NavMenu.razor
T

185 lines
7.9 KiB
Plaintext

@inject IJSRuntime JSRuntime
@inject HttpClient Http
<div class="nav-container onboarding-nav-menu @(IsCollapsed ? "collapsed" : "")">
@* --- Brand / Logo Section --- *@
<div class="nav-header">
<div class="logo-wrapper">
<MudIconButton Icon="@Icons.Material.Filled.Menu" Color="Color.Inherit" OnClick="OnToggleDrawer" Class="drawer-toggle-btn mr-1 d-none d-md-flex" />
<MudIcon Icon="@Icons.Material.Filled.AccessTime" Class="logo-icon" />
<span class="brand-text">Timetracker</span>
</div>
</div>
@* --- Navigation Links --- *@
<div class="nav-content">
<MudNavMenu Class="custom-nav-menu">
<MudTooltip Text="Dashboard" Placement="Placement.Right">
<MudNavLink Href="" Match="NavLinkMatch.All" Icon="@Icons.Material.Filled.Dashboard" Class="custom-nav-link">Dashboard</MudNavLink>
</MudTooltip>
<MudTooltip Text="Wochenübersicht" Placement="Placement.Right">
<MudNavLink Href="week" Icon="@Icons.Material.Filled.CalendarMonth" Class="custom-nav-link">Wochenübersicht</MudNavLink>
</MudTooltip>
<MudTooltip Text="Monatsübersicht" Placement="Placement.Right">
<MudNavLink Href="month" Icon="@Icons.Material.Filled.CalendarViewMonth" Class="custom-nav-link">Monatsübersicht</MudNavLink>
</MudTooltip>
<MudTooltip Text="Statistiken" Placement="Placement.Right">
<MudNavLink Href="stats" Icon="@Icons.Material.Filled.BarChart" Class="custom-nav-link">Statistiken</MudNavLink>
</MudTooltip>
<MudTooltip Text="Feiertage" Placement="Placement.Right">
<MudNavLink Href="feiertage" Icon="@Icons.Material.Filled.Celebration" Class="custom-nav-link">Feiertage</MudNavLink>
</MudTooltip>
<MudTooltip Text="Urlaubs-Maximizer" Placement="Placement.Right">
<MudNavLink Href="urlaub-maximizer" Icon="@Icons.Material.Filled.AutoAwesome" Class="custom-nav-link">Urlaubs-Maximizer</MudNavLink>
</MudTooltip>
<MudTooltip Text="Einstellungen" Placement="Placement.Right">
<MudNavLink Href="settings" Icon="@Icons.Material.Filled.Settings" Class="custom-nav-link">Einstellungen</MudNavLink>
</MudTooltip>
<AuthorizeView Policy="AdminOnly">
<Authorized>
<div class="admin-divider-container">
<span class="admin-divider-text">Admin</span>
<hr class="admin-divider-line" />
</div>
<MudTooltip Text="Firmen verwalten (SaaS)" Placement="Placement.Right">
<MudNavLink Href="superadmin" Icon="@Icons.Material.Filled.Business" Class="custom-nav-link admin-link">
Firmen verwalten
</MudNavLink>
</MudTooltip>
<MudTooltip Text="Benutzerverwaltung" Placement="Placement.Right">
<MudNavLink Href="admin/users" Icon="@Icons.Material.Filled.AdminPanelSettings" Class="custom-nav-link admin-link">
Benutzerverwaltung
</MudNavLink>
</MudTooltip>
</Authorized>
</AuthorizeView>
</MudNavMenu>
</div>
@* --- Footer (User Profile & Action Info) --- *@
<div class="nav-footer">
<AuthorizeView>
<Authorized>
<NavLink href="/profile" class="user-profile-link">
<div class="user-profile-card">
<div class="avatar-container">
<MudAvatar Class="user-avatar">
@GetInitials(context.User.Identity?.Name)
</MudAvatar>
<span class="status-dot"></span>
</div>
<div class="user-info">
<span class="user-name">@context.User.Identity?.Name</span>
<span class="user-status">@GetUserStatus(context.User.Identity?.Name)</span>
</div>
</div>
</NavLink>
</Authorized>
</AuthorizeView>
<MudNavMenu Class="footer-nav-menu">
<AuthorizeView>
<Authorized>
<MudTooltip Text="Abmelden" Placement="Placement.Right">
<MudNavLink Href="/auth/logout" Icon="@Icons.Material.Filled.Logout" Class="custom-nav-link logout-link">Abmelden</MudNavLink>
</MudTooltip>
</Authorized>
</AuthorizeView>
<MudTooltip Text="Changelog anzeigen" Placement="Placement.Right">
<MudNavLink Href="/changelog" Icon="@Icons.Material.Filled.NewReleases" Class="custom-nav-link version-link" OnClick="ClearBadge">
<span class="version-text">Version @timetracker.Client.Components.Pages.Changelog.LatestVersion</span>
@if (_showVersionBadge)
{
<span class="version-badge">1</span>
}
</MudNavLink>
</MudTooltip>
</MudNavMenu>
</div>
</div>
@code {
[PersistentState(AllowUpdates = true)]
public string? PersistentCompanyName { get; set; }
[Parameter] public EventCallback OnToggleDrawer { get; set; }
[Parameter] public bool IsCollapsed { get; set; }
private bool _showVersionBadge;
private string _companyName = "Hauptdomain";
protected override async Task OnInitializedAsync()
{
if (PersistentCompanyName != null)
{
_companyName = PersistentCompanyName;
}
else
{
try
{
var tenantInfo = await Http.GetFromJsonAsync<TenantInfo>("api/tenant/current");
if (tenantInfo?.IsTenant == true && !string.IsNullOrEmpty(tenantInfo.Name))
{
_companyName = tenantInfo.Name;
PersistentCompanyName = _companyName;
}
}
catch
{
// Ignore background error
}
}
}
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
try
{
var lastSeen = await JSRuntime.InvokeAsync<string>("localStorage.getItem", "lastSeenVersion");
var latest = timetracker.Client.Components.Pages.Changelog.LatestVersion;
var isHighlighted = timetracker.Client.Components.Pages.Changelog.IsLatestHighlighted;
_showVersionBadge = isHighlighted && lastSeen != latest;
StateHasChanged();
}
catch
{
// Ignored in SSR
}
}
}
private async Task ClearBadge()
{
_showVersionBadge = false;
try
{
await JSRuntime.InvokeVoidAsync("localStorage.setItem", "lastSeenVersion", timetracker.Client.Components.Pages.Changelog.LatestVersion);
}
catch
{
// Ignored
}
}
private string GetInitials(string? name)
{
if (string.IsNullOrWhiteSpace(name))
return "U";
var parts = name.Split(' ', StringSplitOptions.RemoveEmptyEntries);
if (parts.Length == 1)
return parts[0][..Math.Min(2, parts[0].Length)].ToUpper();
return $"{parts[0][0]}{parts[1][0]}".ToUpper();
}
private string GetUserStatus(string? username)
{
if (string.IsNullOrWhiteSpace(username)) return "";
if (username.Equals("marc", StringComparison.OrdinalIgnoreCase)) return "SuperAdmin";
if (_companyName == "Hauptdomain") return "Einzelnutzer";
return _companyName;
}
}