@page "/audit-logs" @using Microsoft.AspNetCore.Authorization @using Microsoft.AspNetCore.Components.Authorization @using TaskTrackingSystem.Shared.Models.AuditLog @using TaskTrackingSystem.WebApp.Components.Partial @rendermode @(new InteractiveServerRenderMode(prerender: false)) @attribute [Authorize] @inject ApiClientService ApiClient @inject IJSRuntime JS @inject AuthenticationStateProvider AuthStateProvider @AppLocalization.PageTitle("auditLogs", "Audit Logs")

@AppLocalization.PageTitle("auditLogs", "Audit Logs")

@AppLocalization.PageDescription("auditLogs", "Review system activity and changes.")

@if (isLoading) { } else {
@if (PagedLogs.Any()) { @foreach (var entry in PagedLogs.Select((log, index) => (log, index))) { var log = entry.log; } } else { }
No. @AppLocalization.Text("common.date", "Timestamp") @AppLocalization.Text("common.user", "User") @AppLocalization.Text("common.module", "Module") @AppLocalization.Text("common.actions", "Action") @AppLocalization.Text("common.description", "Description") IP Address
@((currentPage - 1) * pageSize + entry.index + 1) @log.CreatedAt.ToString("dd-MM-yyyy HH:mm:ss")
@(log.UserFullName.Length > 0 ? log.UserFullName[0].ToString().ToUpper() : "S")

@log.UserFullName

@@@log.Username

@log.Module @log.Action @log.Description @(string.IsNullOrWhiteSpace(log.IpAddress) ? "N/A" : log.IpAddress)
}
@code { private bool isLoading = true; private List auditLogs = new(); private string searchInput = ""; // Pagination state private int currentPage = 1; private int pageSize = 15; private int totalCount = 0; private int totalPages = 0; private int TotalPages => totalPages; private int TotalCount => totalCount; private IEnumerable PagedLogs => auditLogs; protected override async Task OnInitializedAsync() { await LoadLogs(); } protected override async Task OnAfterRenderAsync(bool firstRender) { await JS.InvokeVoidAsync("initIcons"); } private async Task LoadLogs() { isLoading = true; var client = ApiClient.CreateClient(); try { var url = BuildAuditLogsUrl(); var result = await client.GetFromJsonAsync>(url, Serialization.CaseInsensitive); auditLogs = result?.Items ?? new(); totalCount = result?.TotalCount ?? 0; totalPages = result?.TotalPages ?? 0; currentPage = result?.Page ?? currentPage; pageSize = result?.PageSize ?? pageSize; } catch (Exception ex) { Console.WriteLine($"Load audit logs error: {ex.Message}"); } finally { isLoading = false; } } private void ApplySearch() { currentPage = 1; _ = LoadLogs(); } private void ResetSearch() { searchInput = ""; currentPage = 1; _ = LoadLogs(); } private void HandleKeyUp(KeyboardEventArgs e) { if (e.Key == "Enter") { ApplySearch(); } } private string BuildAuditLogsUrl() { var query = new List { $"page={currentPage}", $"limit={pageSize}" }; if (!string.IsNullOrWhiteSpace(searchInput)) { query.Add($"search={Uri.EscapeDataString(searchInput.Trim())}"); } return $"AuditLog?{string.Join("&", query)}"; } private async Task HandlePageChanged(int page) { currentPage = page; await LoadLogs(); } private async Task HandlePageSizeChanged(int size) { pageSize = size; currentPage = 1; await LoadLogs(); } private string GetActionBadge(string action) { return action.ToLower() switch { "create" => "bg-emerald-50 text-emerald-700 border border-emerald-200", "update" => "bg-amber-50 text-amber-700 border border-amber-200", "delete" => "bg-rose-50 text-rose-700 border border-rose-200", "assignaccess" => "bg-violet-50 text-violet-700 border border-violet-200", _ => "bg-blue-50 text-blue-700 border border-blue-200" }; } }