@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
{
| 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 |
@if (PagedLogs.Any())
{
@foreach (var entry in PagedLogs.Select((log, index) => (log, index)))
{
var log = entry.log;
| @((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)
|
}
}
else
{
}
}
@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"
};
}
}