From 1f0d11490e8ea191b136fb842bfbf6ced02b3a87 Mon Sep 17 00:00:00 2001 From: Ho Ngoc Hai Date: Sat, 28 Feb 2026 04:51:21 +0700 Subject: [PATCH] feat(web-client-tpos): add IamApiService, StaffInfo DTO, and DI registration --- .../src/WebClientTpos.Client/Program.cs | 4 + .../Services/IamApiService.cs | 89 +++++++++++++++++++ .../Services/PosDataService.cs | 4 + 3 files changed, 97 insertions(+) create mode 100644 apps/web-client-tpos-net/src/WebClientTpos.Client/Services/IamApiService.cs diff --git a/apps/web-client-tpos-net/src/WebClientTpos.Client/Program.cs b/apps/web-client-tpos-net/src/WebClientTpos.Client/Program.cs index 001612bd..47620c1e 100644 --- a/apps/web-client-tpos-net/src/WebClientTpos.Client/Program.cs +++ b/apps/web-client-tpos-net/src/WebClientTpos.Client/Program.cs @@ -32,6 +32,10 @@ builder.Services.AddScoped(); // VI: Thêm merchant API service cho quản lý merchant/shop builder.Services.AddScoped(); +// EN: Add IAM API service for roles, audit, users +// VI: Thêm IAM API service cho roles, audit, users +builder.Services.AddScoped(); + // EN: Add MudBlazor services // VI: Thêm các services của MudBlazor builder.Services.AddMudServices(); diff --git a/apps/web-client-tpos-net/src/WebClientTpos.Client/Services/IamApiService.cs b/apps/web-client-tpos-net/src/WebClientTpos.Client/Services/IamApiService.cs new file mode 100644 index 00000000..ffea5eb1 --- /dev/null +++ b/apps/web-client-tpos-net/src/WebClientTpos.Client/Services/IamApiService.cs @@ -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; + +/// +/// EN: Service for calling IAM Service API (Roles, Audit, Users). +/// VI: Service để gọi IAM Service API (Roles, Audit, Users). +/// +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> 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(_jsonOptions); + if (json.TryGetProperty("data", out var data) && data.TryGetProperty("items", out var items)) + return items.Deserialize>(_jsonOptions) ?? new(); + if (json.TryGetProperty("items", out var items2)) + return items2.Deserialize>(_jsonOptions) ?? new(); + return json.Deserialize>(_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> 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(_jsonOptions); + if (json.TryGetProperty("data", out var data) && data.TryGetProperty("items", out var items)) + return items.Deserialize>(_jsonOptions) ?? new(); + if (json.TryGetProperty("items", out var items2)) + return items2.Deserialize>(_jsonOptions) ?? new(); + return json.Deserialize>(_jsonOptions) ?? new(); + } + return new(); + } + catch { return new(); } + } +} diff --git a/apps/web-client-tpos-net/src/WebClientTpos.Client/Services/PosDataService.cs b/apps/web-client-tpos-net/src/WebClientTpos.Client/Services/PosDataService.cs index 4c3dff83..5abb0e3a 100644 --- a/apps/web-client-tpos-net/src/WebClientTpos.Client/Services/PosDataService.cs +++ b/apps/web-client-tpos-net/src/WebClientTpos.Client/Services/PosDataService.cs @@ -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> GetShopsAsync() => await _http.GetFromJsonAsync>("api/bff/shops", _jsonOptions) ?? new(); @@ -39,4 +40,7 @@ public class PosDataService public async Task> GetAppointmentsAsync(Guid shopId) => await _http.GetFromJsonAsync>($"api/bff/shops/{shopId}/appointments", _jsonOptions) ?? new(); + + public async Task> GetStaffAsync() + => await _http.GetFromJsonAsync>("api/bff/staff", _jsonOptions) ?? new(); }