@page "/projects/assign" @using Microsoft.AspNetCore.Authorization @using Microsoft.AspNetCore.Components.Authorization @using TaskTrackingSystem.Shared.Models.Project @using TaskTrackingSystem.Shared.Models.Role @rendermode @(new InteractiveServerRenderMode(prerender: false)) @attribute [Microsoft.AspNetCore.Authorization.Authorize] @inject ApiClientService ApiClient @inject IJSRuntime JS @inject NavigationManager Navigation @inject AuthenticationStateProvider AuthStateProvider @inject MenuAuthorizationService MenuAuthorization @AppLocalization.PageTitle("projectAssignment", "Project Assignment")

@AppLocalization.PageTitle("projectAssignment", "Project Assignment")

@AppLocalization.Text("project.assignDescription", "Assign team members to projects to control their task visibility.")

@if (isLoading) { } else {

@AppLocalization.Text("common.selectProject", "Select Project")

@if (FilteredProjects.Any()) { @foreach (var proj in FilteredProjects) { var isSelected = SelectedProject?.Id == proj.Id; } } else {
@AppLocalization.Text("common.noProjectsFound", "No projects found.")
}
@if (SelectedProject == null) {

@AppLocalization.Text("common.noProjectSelected", "No Project Selected")

@AppLocalization.Text("project.selectProjectPrompt", "Please select a project from the left panel to manage user assignments.")

} else {
@AppLocalization.Text("common.currentlyManaging", "Currently Managing")

@SelectedProject.Name

@if (!string.IsNullOrEmpty(SelectedProject.Description)) {

@SelectedProject.Description

}
@DisplayFormats.Date(SelectedProject.StartDate) - @DisplayFormats.Date(SelectedProject.EndDate)
@if (isAdminUser) {
} else {
@AppLocalization.Text("project.employeesOnly", "Employees only")
}
| | @SelectedUserIds.Count @AppLocalization.Text("common.selected", "selected")
@if (isLoadingMembers) {
} else { @if (FilteredUsers.Any()) {
@foreach (var user in FilteredUsers) { var isChecked = SelectedUserIds.Contains(user.Id); }
} else {
@AppLocalization.Text("common.noTeamMembersFound", "No team members match your search criteria.")
} }
@if (!string.IsNullOrEmpty(statusMessage)) {

@statusMessage

}
@if (canSaveAssignments) { }
}
}
@code { private bool isLoading = true; private bool isLoadingMembers = false; private bool isSaving = false; private bool canSaveAssignments = false; private bool showConfirmDialog = false; private string? statusMessage; private string? successMessage; private bool isError = false; private List projects = new(); private List allUsers = new(); private List roles = new(); private long? adminRoleId; private long? employeeRoleId; private bool isAdminUser; private ProjectDto? SelectedProject { get; set; } private HashSet SelectedUserIds { get; set; } = new(); private string projectSearchInput = ""; private string projectSearch = ""; private string userSearchInput = ""; private string userSearch = ""; private long selectedRoleId = 0; protected override async Task OnInitializedAsync() { var authState = await AuthStateProvider.GetAuthenticationStateAsync(); isAdminUser = authState.User.IsInRole("Admin"); canSaveAssignments = authState.User.IsInRole("Admin") || await MenuAuthorization.HasAccessCodeAsync(authState.User, "Projects_Update"); var client = ApiClient.CreateClient(); try { var projectsTask = client.GetFromJsonAsync>("Project", Serialization.CaseInsensitive); var usersTask = client.GetFromJsonAsync>("User", Serialization.CaseInsensitive); var rolesTask = client.GetFromJsonAsync>("Role", Serialization.CaseInsensitive); await Task.WhenAll(projectsTask, usersTask, rolesTask); projects = projectsTask.Result ?? new(); allUsers = usersTask.Result ?? new(); var allLoadedRoles = rolesTask.Result ?? new(); var adminRole = allLoadedRoles.FirstOrDefault(r => string.Equals(r.Name, "Admin", StringComparison.OrdinalIgnoreCase)); var employeeRole = allLoadedRoles.FirstOrDefault(r => string.Equals(r.Name, "Employee", StringComparison.OrdinalIgnoreCase)); adminRoleId = adminRole?.Id; employeeRoleId = employeeRole?.Id; roles = allLoadedRoles.Where(r => !string.Equals(r.Name, "Admin", StringComparison.OrdinalIgnoreCase)).ToList(); if (!isAdminUser && employeeRoleId.HasValue) { selectedRoleId = employeeRoleId.Value; } } catch (Exception ex) { Console.WriteLine($"Error loading initial data: {ex.Message}"); } finally { isLoading = false; } } protected override async Task OnAfterRenderAsync(bool firstRender) { await JS.InvokeVoidAsync("initIcons"); } private IEnumerable FilteredProjects => string.IsNullOrWhiteSpace(projectSearch) ? projects : projects.Where(p => p.Name.Contains(projectSearch, StringComparison.OrdinalIgnoreCase)); private IEnumerable FilteredUsers { get { var result = allUsers.Where(u => u.IsActive); if (adminRoleId.HasValue) { result = result.Where(u => u.RoleId != adminRoleId.Value); } if (isAdminUser && selectedRoleId > 0) { result = result.Where(u => u.RoleId == selectedRoleId); } else if (!isAdminUser && employeeRoleId.HasValue) { result = result.Where(u => u.RoleId == employeeRoleId.Value); } if (!string.IsNullOrWhiteSpace(userSearch)) { result = result.Where(u => $"{u.FirstName} {u.LastName}".Contains(userSearch, StringComparison.OrdinalIgnoreCase) || u.Username.Contains(userSearch, StringComparison.OrdinalIgnoreCase)); } return result; } } private void ApplyProjectSearch() { projectSearch = projectSearchInput; } private void ApplyUserSearch() { userSearch = userSearchInput; } private void ResetProjectSearch() { projectSearchInput = ""; projectSearch = ""; } private void ResetUserSearch() { userSearchInput = ""; userSearch = ""; selectedRoleId = isAdminUser ? 0 : employeeRoleId ?? 0; } private async Task SelectProject(ProjectDto project) { SelectedProject = project; SelectedUserIds.Clear(); statusMessage = null; isLoadingMembers = true; StateHasChanged(); var client = ApiClient.CreateClient(); try { var membersResult = await client.GetFromJsonAsync>>($"Project/{project.Id}/members", Serialization.CaseInsensitive); if (membersResult?.IsSuccess == true && membersResult.Value != null) { SelectedUserIds = new HashSet(membersResult.Value.Select(u => u.Id)); } } catch (Exception ex) { Console.WriteLine($"Error loading project members: {ex.Message}"); statusMessage = "Failed to load project members."; isError = true; } finally { isLoadingMembers = false; StateHasChanged(); await JS.InvokeVoidAsync("initIcons"); } } private void ToggleUserSelection(long userId, bool isChecked) { if (isChecked) SelectedUserIds.Add(userId); else SelectedUserIds.Remove(userId); statusMessage = null; } private void SelectAllUsers() { foreach (var u in FilteredUsers) { SelectedUserIds.Add(u.Id); } statusMessage = null; } private void DeselectAllUsers() { foreach (var u in FilteredUsers) { SelectedUserIds.Remove(u.Id); } statusMessage = null; } private void RequestSaveConfirmation() { if (SelectedProject == null) return; showConfirmDialog = true; } private void CloseConfirmDialog() { showConfirmDialog = false; } private async Task ConfirmSaveAssignments() { showConfirmDialog = false; await SaveAssignments(); } private async Task SaveAssignments() { if (SelectedProject == null) return; isSaving = true; statusMessage = null; var client = ApiClient.CreateClient(); try { var dto = new AssignMembersDto { UserIds = SelectedUserIds.ToList() }; var response = await client.PostAsJsonAsync($"Project/{SelectedProject.Id}/members", dto); if (response.IsSuccessStatusCode) { statusMessage = "Project assignments saved successfully!"; successMessage = "Assignment saved successfully!"; isError = false; Navigation.NavigateTo("/projects/all"); } else { statusMessage = "Failed to save assignment. Please try again."; isError = true; } } catch (Exception ex) { statusMessage = $"Error: {ex.Message}"; isError = true; } finally { isSaving = false; await JS.InvokeVoidAsync("initIcons"); } } }