feat(web-client-tpos): add IamApiService, StaffInfo DTO, and DI registration

This commit is contained in:
Ho Ngoc Hai
2026-02-28 04:51:21 +07:00
parent 53fda4935c
commit 1f0d11490e
3 changed files with 97 additions and 0 deletions

View File

@@ -32,6 +32,10 @@ builder.Services.AddScoped<WebClientTpos.Client.Services.AuthService>();
// VI: Thêm merchant API service cho quản lý merchant/shop
builder.Services.AddScoped<WebClientTpos.Client.Services.MerchantApiService>();
// EN: Add IAM API service for roles, audit, users
// VI: Thêm IAM API service cho roles, audit, users
builder.Services.AddScoped<WebClientTpos.Client.Services.IamApiService>();
// EN: Add MudBlazor services
// VI: Thêm các services của MudBlazor
builder.Services.AddMudServices();

View File

@@ -0,0 +1,89 @@
// EN: IAM API Service — calls IAM Service API for roles, audit, users.
// VI: IAM API Service — gọi IAM Service API cho roles, audit, users.
using System.Net.Http.Json;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace WebClientTpos.Client.Services;
/// <summary>
/// EN: Service for calling IAM Service API (Roles, Audit, Users).
/// VI: Service để gọi IAM Service API (Roles, Audit, Users).
/// </summary>
public class IamApiService
{
private readonly HttpClient _http;
private readonly AuthService _auth;
private static readonly JsonSerializerOptions _jsonOptions = new()
{
PropertyNameCaseInsensitive = true,
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull
};
public IamApiService(HttpClient http, AuthService auth)
{
_http = http;
_auth = auth;
}
private async Task SetAuthHeader()
{
var token = await _auth.GetTokenAsync();
if (!string.IsNullOrEmpty(token))
_http.DefaultRequestHeaders.Authorization =
new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", token);
}
// ─── ROLES ───
public record RoleDto(Guid Id, string Name, string? Description, bool IsSystem, DateTime CreatedAt, int? UserCount);
public async Task<List<RoleDto>> GetRolesAsync()
{
await SetAuthHeader();
try
{
var response = await _http.GetAsync("/api/iam/api/v1/roles?pageSize=50");
if (response.IsSuccessStatusCode)
{
var json = await response.Content.ReadFromJsonAsync<JsonElement>(_jsonOptions);
if (json.TryGetProperty("data", out var data) && data.TryGetProperty("items", out var items))
return items.Deserialize<List<RoleDto>>(_jsonOptions) ?? new();
if (json.TryGetProperty("items", out var items2))
return items2.Deserialize<List<RoleDto>>(_jsonOptions) ?? new();
return json.Deserialize<List<RoleDto>>(_jsonOptions) ?? new();
}
return new();
}
catch { return new(); }
}
// ─── AUDIT LOGS ───
public record AuditLogDto(
int? Id, DateTime? Timestamp, string? EventType, string? ActorId,
string? ActorName, string? ResourceType, string? ResourceId,
string? Details, string? IpAddress, string? Status);
public async Task<List<AuditLogDto>> GetAuditLogsAsync(int take = 50)
{
await SetAuthHeader();
try
{
var response = await _http.GetAsync($"/api/iam/api/v1/audit/logs?take={take}");
if (response.IsSuccessStatusCode)
{
var json = await response.Content.ReadFromJsonAsync<JsonElement>(_jsonOptions);
if (json.TryGetProperty("data", out var data) && data.TryGetProperty("items", out var items))
return items.Deserialize<List<AuditLogDto>>(_jsonOptions) ?? new();
if (json.TryGetProperty("items", out var items2))
return items2.Deserialize<List<AuditLogDto>>(_jsonOptions) ?? new();
return json.Deserialize<List<AuditLogDto>>(_jsonOptions) ?? new();
}
return new();
}
catch { return new(); }
}
}

View File

@@ -21,6 +21,7 @@ public class PosDataService
public record CategoryInfo(Guid Id, string Name, string? Description, int DisplayOrder);
public record TableInfo(Guid Id, string TableNumber, int Capacity, string? Zone, string Status, Guid? SessionId, int? GuestCount, DateTime? StartedAt);
public record AppointmentInfo(Guid Id, Guid? CustomerId, Guid? StaffId, Guid? ResourceId, Guid ServiceId, DateTime StartTime, DateTime EndTime, string Status, string? ResourceName);
public record StaffInfo(Guid Id, Guid? UserId, string? EmployeeCode, string? Phone, string? Email, DateTime? JoinedAt, DateTime? TerminatedAt, string? Role, string? Status, string? ShopName);
public async Task<List<ShopInfo>> GetShopsAsync()
=> await _http.GetFromJsonAsync<List<ShopInfo>>("api/bff/shops", _jsonOptions) ?? new();
@@ -39,4 +40,7 @@ public class PosDataService
public async Task<List<AppointmentInfo>> GetAppointmentsAsync(Guid shopId)
=> await _http.GetFromJsonAsync<List<AppointmentInfo>>($"api/bff/shops/{shopId}/appointments", _jsonOptions) ?? new();
public async Task<List<StaffInfo>> GetStaffAsync()
=> await _http.GetFromJsonAsync<List<StaffInfo>>("api/bff/staff", _jsonOptions) ?? new();
}