@page "/user-directory" @attribute [Authorize] @inject IUserSessionService Session @inject IGraphUserDirectoryService GraphSvc @inject IAuditService Audit @inject TranslationSource T @rendermode InteractiveServer

@T["directory.grp.browse"]

@T["directory.subtitle"]

@if (!Session.HasProfile) { return; }
@if (!string.IsNullOrEmpty(_error)) {
@_error
} @if (_users.Count > 0) {
@T["directory.title.users"] @_users.Count
@foreach (var u in FilteredUsers.Take(500)) { }
@T["directory.col.name"]@T["directory.col.upn"]@T["directory.col.department"]@T["directory.col.jobtitle"]@T["directory.col.type"]
@u.DisplayName @u.UserPrincipalName @u.Department @u.JobTitle @(u.UserType ?? T["directory.type.member"])
@if (FilteredUsers.Count() > 500) {
@string.Format(T["directory.showing500"], FilteredUsers.Count())
}
} @code { private bool _includeGuests, _running; private string _status = string.Empty, _error = string.Empty, _filter = string.Empty; private int _loadCount; private List _users = new(); private IEnumerable FilteredUsers => string.IsNullOrWhiteSpace(_filter) ? _users : _users.Where(u => u.DisplayName.Contains(_filter, StringComparison.OrdinalIgnoreCase) || u.UserPrincipalName.Contains(_filter, StringComparison.OrdinalIgnoreCase)); private async Task LoadUsers() { _error = string.Empty; _users.Clear(); _running = true; _loadCount = 0; var progress = new Progress(count => { _loadCount = count; InvokeAsync(StateHasChanged); }); try { _users = (await GraphSvc.GetUsersAsync(Session.CurrentProfile!, _includeGuests, progress)).ToList(); _status = string.Format(T["directory.status.loaded"], _users.Count); await Audit.LogAsync("UserDirectoryLoad", Session.CurrentProfile?.Name ?? "", Array.Empty(), $"{_users.Count} users; guests={_includeGuests}"); } catch (Exception ex) { _error = ex.Message; } finally { _running = false; await InvokeAsync(StateHasChanged); } } }