Spaces:
Sleeping
Sleeping
Yuyuqt
add: books, borrowings, home, login, membership, register, reward, userinsights, wishlist, themes
6f32ae8 | using System.Text.Json.Serialization; | |
| using System.Net.Http.Json; | |
| using System.Text.Json; | |
| using LibraryManagement.Shared.Models; // Changed from LibraryManagement.Shared.Models | |
| namespace Frontend.Services | |
| { | |
| public class LibraryApiClient | |
| { | |
| public async Task<IEnumerable<LoyaltyRewardDto>> GetActiveRewardsAsync() | |
| { | |
| try | |
| { | |
| var options = new JsonSerializerOptions { PropertyNameCaseInsensitive = true, NumberHandling = JsonNumberHandling.AllowReadingFromString }; | |
| return await _httpClient.GetFromJsonAsync<IEnumerable<LoyaltyRewardDto>>("api/Loyalty/rewards", options) ?? Enumerable.Empty<LoyaltyRewardDto>(); | |
| } | |
| catch { return Enumerable.Empty<LoyaltyRewardDto>(); } | |
| } | |
| private readonly HttpClient _httpClient; | |
| private readonly IHttpContextAccessor _httpContextAccessor; | |
| public LibraryApiClient(IHttpClientFactory httpClientFactory, IHttpContextAccessor httpContextAccessor) | |
| { | |
| _httpClient = httpClientFactory.CreateClient("LibraryBackend"); | |
| _httpContextAccessor = httpContextAccessor; | |
| AddAuthHeaderFromCookie(); | |
| } | |
| private void AddAuthHeaderFromCookie() | |
| { | |
| var token = _httpContextAccessor.HttpContext?.Request.Cookies["AuthToken"]; | |
| if (!string.IsNullOrEmpty(token)) | |
| { | |
| _httpClient.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", token); | |
| } | |
| } | |
| public void SetToken(string token) | |
| { | |
| if (!string.IsNullOrEmpty(token)) | |
| { | |
| _httpClient.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", token); | |
| } | |
| } | |
| public async Task<AuthResponse?> LoginAsync(LoginRequest request) | |
| { | |
| var response = await _httpClient.PostAsJsonAsync("api/auth/login", request); | |
| return response.IsSuccessStatusCode ? await response.Content.ReadFromJsonAsync<AuthResponse>() : null; | |
| } | |
| public async Task<AuthResponse?> RegisterAsync(RegisterRequest request) | |
| { | |
| var response = await _httpClient.PostAsJsonAsync("api/auth/register", request); | |
| return response.IsSuccessStatusCode ? await response.Content.ReadFromJsonAsync<AuthResponse>() : null; | |
| } | |
| public async Task<object?> GetProfileAsync() | |
| { | |
| return await _httpClient.GetFromJsonAsync<object>("api/auth/me"); | |
| } | |
| public async Task<IEnumerable<BookDto>> GetBooksAsync(int? categoryId = null) | |
| { | |
| var url = categoryId.HasValue ? $"api/books?categoryId={categoryId}" : "api/books"; | |
| return await _httpClient.GetFromJsonAsync<IEnumerable<BookDto>>(url) ?? Enumerable.Empty<BookDto>(); | |
| } | |
| public async Task<BookDto?> GetBookAsync(int id) | |
| { | |
| return await _httpClient.GetFromJsonAsync<BookDto>($"api/books/{id}"); | |
| } | |
| public async Task<BookDto?> CreateBookAsync(BookCreateRequest request) | |
| { | |
| var response = await _httpClient.PostAsJsonAsync("api/books", request); | |
| return response.IsSuccessStatusCode ? await response.Content.ReadFromJsonAsync<BookDto>() : null; | |
| } | |
| public async Task<BookDto?> UpdateBookAsync(int id, BookUpdateRequest request) | |
| { | |
| var response = await _httpClient.PutAsJsonAsync($"api/books/{id}", request); | |
| return response.IsSuccessStatusCode ? await response.Content.ReadFromJsonAsync<BookDto>() : null; | |
| } | |
| public async Task<bool> DeleteBookAsync(int id) | |
| { | |
| var response = await _httpClient.DeleteAsync($"api/books/{id}"); | |
| return response.IsSuccessStatusCode; | |
| } | |
| public async Task<BorrowingDto?> BorrowBookAsync(BorrowRequest request) | |
| { | |
| var response = await _httpClient.PostAsJsonAsync("api/borrowings/borrow", request); | |
| return response.IsSuccessStatusCode ? await response.Content.ReadFromJsonAsync<BorrowingDto>() : null; | |
| } | |
| public async Task<BorrowingDto?> ReturnBookAsync(Guid id) | |
| { | |
| var response = await _httpClient.PostAsync($"api/borrowings/return/{id}", null); | |
| return response.IsSuccessStatusCode ? await response.Content.ReadFromJsonAsync<BorrowingDto>() : null; | |
| } | |
| public async Task<IEnumerable<BorrowingDto>> GetMyBorrowingsAsync() | |
| { | |
| return await _httpClient.GetFromJsonAsync<IEnumerable<BorrowingDto>>("api/borrowings/me") ?? Enumerable.Empty<BorrowingDto>(); | |
| } | |
| public async Task<IEnumerable<BorrowingDto>> GetAllBorrowingsAsync() | |
| { | |
| return await _httpClient.GetFromJsonAsync<IEnumerable<BorrowingDto>>("api/borrowings") ?? Enumerable.Empty<BorrowingDto>(); | |
| } | |
| public async Task<IEnumerable<CategoryDto>> GetCategoriesAsync() | |
| { | |
| return await _httpClient.GetFromJsonAsync<IEnumerable<CategoryDto>>("api/categories") ?? Enumerable.Empty<CategoryDto>(); | |
| } | |
| public async Task<IEnumerable<CategoryDto>> GetCategoriesWithBooksAsync() | |
| { | |
| return await _httpClient.GetFromJsonAsync<IEnumerable<CategoryDto>>("api/categories/with-books") ?? Enumerable.Empty<CategoryDto>(); | |
| } | |
| public async Task<CategoryDto?> CreateCategoryAsync(CategoryCreateRequest request) | |
| { | |
| var response = await _httpClient.PostAsJsonAsync("api/categories", request); | |
| return response.IsSuccessStatusCode ? await response.Content.ReadFromJsonAsync<CategoryDto>() : null; | |
| } | |
| public async Task<bool> DeleteCategoryAsync(int id) | |
| { | |
| var response = await _httpClient.DeleteAsync($"api/categories/{id}"); | |
| return response.IsSuccessStatusCode; | |
| } | |
| public async Task<IEnumerable<MembershipDto>> GetMembershipsAsync() | |
| { | |
| return await _httpClient.GetFromJsonAsync<IEnumerable<MembershipDto>>("api/memberships") ?? Enumerable.Empty<MembershipDto>(); | |
| } | |
| public async Task<SubscriptionDto?> GetMySubscriptionAsync() | |
| { | |
| try | |
| { | |
| return await _httpClient.GetFromJsonAsync<SubscriptionDto>("api/subscriptions/me"); | |
| } | |
| catch { return null; } | |
| } | |
| public async Task<IEnumerable<SubscriptionDto>> GetMyAllSubscriptionsAsync() | |
| { | |
| try | |
| { | |
| return await _httpClient.GetFromJsonAsync<IEnumerable<SubscriptionDto>>("api/subscriptions/me/all") ?? Enumerable.Empty<SubscriptionDto>(); | |
| } | |
| catch { return Enumerable.Empty<SubscriptionDto>(); } | |
| } | |
| public async Task<SubscriptionDto?> SubscribeAsync(SubscribeRequest request) | |
| { | |
| var response = await _httpClient.PostAsJsonAsync("api/subscriptions/subscribe", request); | |
| return response.IsSuccessStatusCode ? await response.Content.ReadFromJsonAsync<SubscriptionDto>() : null; | |
| } | |
| public async Task<SubscriptionDto?> GetUserSubscriptionAsync(Guid userId) | |
| { | |
| try | |
| { | |
| return await _httpClient.GetFromJsonAsync<SubscriptionDto>($"api/subscriptions/user/{userId}"); | |
| } | |
| catch { return null; } | |
| } | |
| public async Task<SubscriptionDto?> AdminSubscribeAsync(AdminSubscribeRequest request) | |
| { | |
| var response = await _httpClient.PostAsJsonAsync("api/subscriptions/admin-subscribe", request); | |
| return response.IsSuccessStatusCode ? await response.Content.ReadFromJsonAsync<SubscriptionDto>() : null; | |
| } | |
| public async Task<IEnumerable<SubscriptionDto>> GetAllSubscriptionsAsync() | |
| { | |
| return await _httpClient.GetFromJsonAsync<IEnumerable<SubscriptionDto>>("api/subscriptions/all") ?? Enumerable.Empty<SubscriptionDto>(); | |
| } | |
| public async Task<LoyaltyAccountDto?> GetMyLoyaltyAccountAsync() | |
| { | |
| try | |
| { | |
| // Using exact casing for the route to be safe | |
| var response = await _httpClient.GetAsync("api/Loyalty/my-account"); | |
| if (response.IsSuccessStatusCode) | |
| { | |
| // JsonPropertyName attributes in LoyaltyAccountDto will handle the mapping | |
| // and correctly populate CurrentBalance from the backend's currentBalance | |
| return await response.Content.ReadFromJsonAsync<LoyaltyAccountDto>(); | |
| } | |
| else | |
| { | |
| var error = await response.Content.ReadAsStringAsync(); | |
| System.Diagnostics.Debug.WriteLine($"Loyalty API error: {response.StatusCode} - {error}"); | |
| // Throw custom exception or return null based on error | |
| } | |
| return null; | |
| } | |
| catch (Exception ex) | |
| { | |
| System.Diagnostics.Debug.WriteLine($"Loyalty API Exception: {ex.Message}"); | |
| return null; | |
| } | |
| } | |
| public async Task<IEnumerable<LoyaltyRedemptionDto>> GetMyRedemptionsAsync() | |
| { | |
| try | |
| { | |
| return await _httpClient.GetFromJsonAsync<IEnumerable<LoyaltyRedemptionDto>>("api/Loyalty/my-redemptions") ?? Enumerable.Empty<LoyaltyRedemptionDto>(); | |
| } | |
| catch { return Enumerable.Empty<LoyaltyRedemptionDto>(); } | |
| } | |
| public async Task<IEnumerable<LoyaltyRedemptionDto>> GetMyPendingRedemptionsAsync() | |
| { | |
| try | |
| { | |
| return await _httpClient.GetFromJsonAsync<IEnumerable<LoyaltyRedemptionDto>>("api/Loyalty/my-pending-redemptions") ?? Enumerable.Empty<LoyaltyRedemptionDto>(); | |
| } | |
| catch { return Enumerable.Empty<LoyaltyRedemptionDto>(); } | |
| } | |
| public async Task<IEnumerable<PointHistoryEntryDto>> GetPointsHistoryAsync(string accountId) | |
| { | |
| try | |
| { | |
| // Call the Backend's proxy endpoint instead of trying to hit the external API directly | |
| return await _httpClient.GetFromJsonAsync<IEnumerable<PointHistoryEntryDto>>("api/Loyalty/my-points-history") ?? Enumerable.Empty<PointHistoryEntryDto>(); | |
| } | |
| catch { return Enumerable.Empty<PointHistoryEntryDto>(); } | |
| } | |
| public async Task<IEnumerable<UserPointsHistoryDto>> GetAllMembersPointsHistoryAsync() | |
| { | |
| try { | |
| var options = new JsonSerializerOptions { PropertyNameCaseInsensitive = true, NumberHandling = JsonNumberHandling.AllowReadingFromString }; | |
| var response = await _httpClient.GetAsync("api/Loyalty/admin/all-points-history"); | |
| var raw = await response.Content.ReadAsStringAsync(); | |
| if (!response.IsSuccessStatusCode) | |
| return Enumerable.Empty<UserPointsHistoryDto>(); | |
| var data = JsonSerializer.Deserialize<List<UserPointsHistoryDto>>(raw, options) ?? new List<UserPointsHistoryDto>(); | |
| foreach (var member in data) | |
| { | |
| member.History = member.History?.ToList() ?? new List<PointHistoryEntryDto>(); | |
| member.Redemptions = member.Redemptions?.ToList() ?? new List<LoyaltyRedemptionDto>(); | |
| } | |
| return data; | |
| } catch { return Enumerable.Empty<UserPointsHistoryDto>(); } | |
| } | |
| public async Task<bool> RequestReturnAsync(Guid borrowingId) | |
| { | |
| var response = await _httpClient.PostAsync($"api/borrowings/return-request/{borrowingId}", null); | |
| return response.IsSuccessStatusCode; | |
| } | |
| public async Task<(bool Success, string Message)> ClaimRewardAsync(string rewardId, string? notes = null) | |
| { | |
| try | |
| { | |
| var request = new ClaimRewardRequestDto { RewardId = rewardId, Notes = notes }; | |
| var response = await _httpClient.PostAsJsonAsync("api/Loyalty/claim", request); | |
| if (response.IsSuccessStatusCode) | |
| { | |
| var result = await response.Content.ReadFromJsonAsync<JsonDocument>(); | |
| string msg = "Reward claimed successfully!"; | |
| if (result != null && result.RootElement.TryGetProperty("message", out var msgElement)) | |
| { | |
| msg = msgElement.GetString() ?? msg; | |
| } | |
| return (true, msg); | |
| } | |
| else | |
| { | |
| var error = await response.Content.ReadFromJsonAsync<JsonDocument>(); | |
| string msg = "Failed to claim reward."; | |
| if (error != null && error.RootElement.TryGetProperty("message", out var msgElement)) | |
| { | |
| msg = msgElement.GetString() ?? msg; | |
| } | |
| return (false, msg); | |
| } | |
| } | |
| catch (Exception ex) | |
| { | |
| return (false, $"An error occurred: {ex.Message}"); | |
| } | |
| } | |
| public async Task<IEnumerable<UserDto>> GetUsersAsync() | |
| { | |
| return await _httpClient.GetFromJsonAsync<IEnumerable<UserDto>>("api/users") ?? Enumerable.Empty<UserDto>(); | |
| } | |
| public async Task<UserDto?> GetUserAsync(Guid id) | |
| { | |
| return await _httpClient.GetFromJsonAsync<UserDto>($"api/users/{id}"); | |
| } | |
| public async Task<UserDto?> CreateUserAsync(UserCreateRequest request) | |
| { | |
| var response = await _httpClient.PostAsJsonAsync("api/users", request); | |
| return response.IsSuccessStatusCode ? await response.Content.ReadFromJsonAsync<UserDto>() : null; | |
| } | |
| public async Task<UserDto?> UpdateUserAsync(Guid id, UserUpdateRequest request) | |
| { | |
| var response = await _httpClient.PutAsJsonAsync($"api/users/{id}", request); | |
| return response.IsSuccessStatusCode ? await response.Content.ReadFromJsonAsync<UserDto>() : null; | |
| } | |
| public async Task<bool> UpdateUserRoleAsync(Guid id, string role) | |
| { | |
| var response = await _httpClient.PutAsJsonAsync($"api/users/role/{id}", new UserRoleUpdateRequest { Role = role }); | |
| return response.IsSuccessStatusCode; | |
| } | |
| public async Task<bool> DeleteUserAsync(Guid id) | |
| { | |
| var response = await _httpClient.DeleteAsync($"api/users/{id}"); | |
| return response.IsSuccessStatusCode; | |
| } | |
| public async Task<IEnumerable<LoyaltyRedemptionDto>> GetPendingRedemptionsAsync() | |
| { | |
| try | |
| { | |
| var response = await _httpClient.GetAsync("api/Loyalty/admin/redemptions/pending"); | |
| if (response.IsSuccessStatusCode) | |
| { | |
| var options = new JsonSerializerOptions { PropertyNameCaseInsensitive = true, NumberHandling = JsonNumberHandling.AllowReadingFromString }; | |
| return await response.Content.ReadFromJsonAsync<IEnumerable<LoyaltyRedemptionDto>>(options) ?? Enumerable.Empty<LoyaltyRedemptionDto>(); | |
| } | |
| return Enumerable.Empty<LoyaltyRedemptionDto>(); | |
| } | |
| catch { return Enumerable.Empty<LoyaltyRedemptionDto>(); } | |
| } | |
| public async Task<(bool Success, string Message)> FulfillRedemptionAsync(string id) | |
| { | |
| try | |
| { | |
| var response = await _httpClient.PostAsync($"api/Loyalty/admin/redemptions/{id}/fulfill", null); | |
| if (response.IsSuccessStatusCode) | |
| { | |
| var result = await response.Content.ReadFromJsonAsync<JsonDocument>(); | |
| string msg = "Redemption fulfilled successfully!"; | |
| if (result != null && result.RootElement.TryGetProperty("message", out var msgElement)) | |
| { | |
| msg = msgElement.GetString() ?? msg; | |
| } | |
| return (true, msg); | |
| } | |
| else | |
| { | |
| var error = await response.Content.ReadFromJsonAsync<JsonDocument>(); | |
| string msg = "Failed to fulfill redemption."; | |
| if (error != null && error.RootElement.TryGetProperty("message", out var msgElement)) | |
| { | |
| msg = msgElement.GetString() ?? msg; | |
| } | |
| return (false, msg); | |
| } | |
| } | |
| catch (Exception ex) { return (false, $"Error: {ex.Message}"); } | |
| } | |
| } | |
| } | |