@inherits LayoutComponentBase @implements IDisposable @using System.Security.Claims @inject TaskTrackingSystem.WebApp.Localization.UiLanguageService Language

@CurrentPageTitle

@if (isAuthorizedPage) { @Body } else {

@Language.Texts.AccessDenied

@Language.Texts.AccessDeniedDescription

@Language.Texts.BackToDashboard
}
@code { [Inject] private NavigationManager Navigation { get; set; } = default!; [Inject] private IJSRuntime JS { get; set; } = default!; [Inject] private MenuAuthorizationService MenuAuthorization { get; set; } = default!; [Inject] private Microsoft.AspNetCore.Components.Authorization.AuthenticationStateProvider AuthStateProvider { get; set; } = default!; private bool isAuthorizedPage = true; private string dashboardHref = "/dashboard"; private bool IsDashboardPage => string.IsNullOrEmpty(Navigation.ToBaseRelativePath(Navigation.Uri)) || Navigation.ToBaseRelativePath(Navigation.Uri).Split('?')[0].Trim('/') is "dashboard" or "Home" or ""; private string CurrentRoute => Navigation.ToBaseRelativePath(Navigation.Uri).Split('?')[0].Trim('/'); private string CurrentPageTitle { get { if (CurrentRoute.StartsWith("projects/", StringComparison.OrdinalIgnoreCase) && CurrentRoute.EndsWith("/tasks", StringComparison.OrdinalIgnoreCase)) { return AppLocalization.PageTitle("kanbanBoard", "Kanban Board"); } if (CurrentRoute.StartsWith("tasks/", StringComparison.OrdinalIgnoreCase)) { return AppLocalization.PageTitle("taskDetails", "Task Details"); } return CurrentRoute switch { "" or "dashboard" or "Home" => AppLocalization.PageTitle("dashboard", "Dashboard"), "dashboard/manager" => AppLocalization.PageTitle("managerDashboard", "Manager Dashboard"), "dashboard/employee" => AppLocalization.PageTitle("employeeDashboard", "Employee Dashboard"), "projects" or "projects/all" => AppLocalization.PageTitle("projects", "Projects"), "projects/assign" => AppLocalization.PageTitle("projectAssignment", "Project Assignment"), "tasks" or "tasks/all" => AppLocalization.PageTitle("tasks", "Tasks"), "board" => AppLocalization.PageTitle("kanbanBoard", "Kanban Board"), "tasks/assign" => AppLocalization.PageTitle("taskAssignment", "Task Assignment"), "issues" or "issues/all" => AppLocalization.PageTitle("issues", "Issues"), "issues/add" => AppLocalization.PageTitle("addIssue", "Add Issue"), "reports/tasks" => AppLocalization.PageTitle("taskReport", "Task Report"), "reports/time" => AppLocalization.PageTitle("timeTracking", "Time Tracking"), "reports/projects" => AppLocalization.PageTitle("projectProgress", "Project Progress"), "reports/overdue" => AppLocalization.PageTitle("overdueTasks", "Overdue Tasks"), "reports/employees" => AppLocalization.PageTitle("employeeReport", "Employee Report"), "roles" => AppLocalization.PageTitle("rolesAccess", "Roles & Access"), "users" => AppLocalization.PageTitle("users", "Users"), "audit-logs" => AppLocalization.PageTitle("auditLogs", "Audit Logs"), _ => AppLocalization.Text("common.workspace", "Workspace") }; } } private string CurrentPageDescription => CurrentPageTitle switch { var title when title == AppLocalization.PageTitle("dashboard", "Dashboard") => AppLocalization.PageDescription("dashboard", "A quick overview of work, risk, and progress."), var title when title == AppLocalization.PageTitle("managerDashboard", "Manager Dashboard") => AppLocalization.PageDescription("managerDashboard", "Track projects, people, and delivery health."), var title when title == AppLocalization.PageTitle("employeeDashboard", "Employee Dashboard") => AppLocalization.PageDescription("employeeDashboard", "Focus on your tasks, due dates, and progress."), var title when title == AppLocalization.PageTitle("projects", "Projects") => AppLocalization.PageDescription("projects", "Manage project plans, timelines, and assignments."), var title when title == AppLocalization.PageTitle("projectAssignment", "Project Assignment") => AppLocalization.PageDescription("projectAssignment", "Assign team members to the right projects."), var title when title == AppLocalization.PageTitle("tasks", "Tasks") => AppLocalization.PageDescription("tasks", "Review, filter, and update work items."), var title when title == AppLocalization.PageTitle("kanbanBoard", "Kanban Board") => AppLocalization.PageDescription("kanbanBoard", "Move work through status columns."), var title when title == AppLocalization.PageTitle("taskAssignment", "Task Assignment") => AppLocalization.PageDescription("taskAssignment", "Assign tasks to project members."), var title when title == AppLocalization.PageTitle("issues", "Issues") => AppLocalization.PageDescription("issues", "Track blockers, notes, and daily work progress."), var title when title == AppLocalization.PageTitle("addIssue", "Add Issue") => AppLocalization.PageDescription("addIssue", "Record a new issue against a task."), var title when title == AppLocalization.PageTitle("rolesAccess", "Roles & Access") => AppLocalization.PageDescription("rolesAccess", "Control user roles, menus, and permissions."), var title when title == AppLocalization.PageTitle("users", "Users") => AppLocalization.PageDescription("users", "Manage people, status, and account details."), var title when title == AppLocalization.PageTitle("auditLogs", "Audit Logs") => AppLocalization.PageDescription("auditLogs", "Review system activity and changes."), var title when title.Contains(AppLocalization.Text("page.taskReport", "Task Report"), StringComparison.OrdinalIgnoreCase) => AppLocalization.Text("page.taskReport.desc", "Analyze work data and export reports."), var title when title.Contains(AppLocalization.Text("page.timeTracking", "Time Tracking"), StringComparison.OrdinalIgnoreCase) => AppLocalization.Text("page.timeTracking.desc", "Review effort by task, project, and assignee."), var title when title.Contains(AppLocalization.Text("page.projectProgress", "Project Progress"), StringComparison.OrdinalIgnoreCase) => AppLocalization.Text("page.projectProgress.desc", "Monitor delivery health across active projects."), var title when title.Contains(AppLocalization.Text("page.overdueTasks", "Overdue Tasks"), StringComparison.OrdinalIgnoreCase) => AppLocalization.Text("page.overdueTasks.desc", "Focus on delayed work that needs attention."), var title when title.Contains(AppLocalization.Text("page.employeeReport", "Employee Report"), StringComparison.OrdinalIgnoreCase) => AppLocalization.Text("page.employeeReport.desc", "See how work is distributed across people."), var title when title.Contains(AppLocalization.Text("page.issueReport", "Issue Report"), StringComparison.OrdinalIgnoreCase) => AppLocalization.Text("page.issueReport.desc", "Track daily execution, backlog health, and issue-level effort."), _ => AppLocalization.Text("common.workspace", "Workspace") }; protected override async Task OnInitializedAsync() { Language.Changed += OnLanguageChanged; Navigation.LocationChanged += OnLocationChanged; var relativePath = Navigation.ToBaseRelativePath(Navigation.Uri); await UpdateAuthorizationAsync(relativePath); } private void OnLocationChanged(object? sender, Microsoft.AspNetCore.Components.Routing.LocationChangedEventArgs e) { UpdateAuthorization(); } private void UpdateAuthorization() { var relativePath = Navigation.ToBaseRelativePath(Navigation.Uri); _ = UpdateAuthorizationAsync(relativePath); } private void OnLanguageChanged() { _ = InvokeAsync(StateHasChanged); } private async Task UpdateAuthorizationAsync(string relativePath) { var authState = await AuthStateProvider.GetAuthenticationStateAsync(); var user = authState.User; if (user.Identity?.IsAuthenticated != true) { if (!MenuAuthorizationService.IsPublicRoute(relativePath)) { var returnPath = new Uri(Navigation.Uri).AbsolutePath; Navigation.NavigateTo($"/login?ReturnUrl={Uri.EscapeDataString(returnPath)}"); } isAuthorizedPage = MenuAuthorizationService.IsPublicRoute(relativePath); await InvokeAsync(StateHasChanged); return; } var menus = await MenuAuthorization.GetUserMenusAsync(user); dashboardHref = ResolveDashboardHref(menus); var allowed = MenuAuthorization.IsRouteAllowed(user, relativePath); isAuthorizedPage = allowed; await InvokeAsync(StateHasChanged); } protected override async Task OnAfterRenderAsync(bool firstRender) { await JS.InvokeVoidAsync("initIcons"); } public void Dispose() { Navigation.LocationChanged -= OnLocationChanged; Language.Changed -= OnLanguageChanged; } private static string ResolveDashboardHref(IEnumerable menus) { foreach (var menu in menus) { var found = ResolveDashboardHref(menu); if (!string.IsNullOrWhiteSpace(found)) { return found; } } return "/dashboard"; } private static string? ResolveDashboardHref(TaskTrackingSystem.Shared.Models.Menu.MenuDto menu) { if (!string.IsNullOrWhiteSpace(menu.MenuUrl) && menu.MenuUrl.StartsWith("/dashboard", StringComparison.OrdinalIgnoreCase)) { return menu.MenuUrl; } foreach (var subMenu in menu.SubMenus) { var found = ResolveDashboardHref(subMenu); if (!string.IsNullOrWhiteSpace(found)) { return found; } } return null; } }