initial commit

This commit is contained in:
2026-07-21 14:41:46 +07:00
commit 1bfa3dd1c2
1159 changed files with 88228 additions and 0 deletions
+153
View File
@@ -0,0 +1,153 @@
using Indotalent.ConfigBackEnd.Interfaces;
using Indotalent.Features.Account.Login.Cqrs;
using Indotalent.Infrastructure.Authentication.Identity;
using Indotalent.Shared.Models;
using Microsoft.AspNetCore.Components;
using MudBlazor;
using RestSharp;
using System.Net;
namespace Indotalent.ConfigFrontEnd.Common;
public abstract class BaseService
{
protected readonly IHttpClientFactory ClientFactory;
protected readonly NavigationManager Nav;
protected readonly ISnackbar Snackbar;
protected readonly ICurrentUserService CurrentUserService;
protected readonly TokenProvider TokenProvider;
public BaseService(
IHttpClientFactory clientFactory,
NavigationManager nav,
ISnackbar snackbar,
ICurrentUserService currentUserService,
TokenProvider tokenProvider)
{
ClientFactory = clientFactory;
Nav = nav;
Snackbar = snackbar;
CurrentUserService = currentUserService;
TokenProvider = tokenProvider;
}
protected HttpClient CreateClient()
{
var client = ClientFactory.CreateClient();
if (client.BaseAddress == null)
{
client.BaseAddress = new Uri(Nav.BaseUri);
}
return client;
}
protected async Task<ApiResponse<T>?> ExecuteWithResponseAsync<T>(RestClient client, RestRequest request)
{
try
{
if (!string.IsNullOrEmpty(TokenProvider.Token))
request.AddOrUpdateHeader("Authorization", $"Bearer {TokenProvider.Token}");
if (!string.IsNullOrEmpty(TokenProvider.RefreshToken))
request.AddOrUpdateHeader("X-Refresh-Token", TokenProvider.RefreshToken);
if (!string.IsNullOrEmpty(CurrentUserService.UserId))
{
request.AddOrUpdateHeader("X-UserId", CurrentUserService.UserId);
request.AddOrUpdateHeader("X-UserName", CurrentUserService.UserName ?? string.Empty);
request.AddOrUpdateHeader("X-Email", CurrentUserService.Email ?? string.Empty);
request.AddOrUpdateHeader("X-FullName", CurrentUserService.FullName ?? string.Empty);
}
var response = await client.ExecuteAsync<ApiResponse<T>>(request);
if (response.StatusCode == HttpStatusCode.Unauthorized)
{
var httpClient = CreateClient();
var refreshRequestMessage = new HttpRequestMessage(HttpMethod.Post, "/api/account/refresh-token");
if (!string.IsNullOrEmpty(TokenProvider.RefreshToken))
{
refreshRequestMessage.Headers.Add("X-Refresh-Token", TokenProvider.RefreshToken);
}
var refreshResponse = await httpClient.SendAsync(refreshRequestMessage);
if (refreshResponse.IsSuccessStatusCode)
{
var result = await refreshResponse.Content.ReadFromJsonAsync<LoginResponse>();
if (result != null && !string.IsNullOrEmpty(result.Token))
{
TokenProvider.Token = result.Token;
request.AddOrUpdateHeader("Authorization", $"Bearer {TokenProvider.Token}");
response = await client.ExecuteAsync<ApiResponse<T>>(request);
}
}
else
{
Nav.NavigateTo("/account/login");
return default;
}
}
if (response.Data != null)
{
if (!response.Data.IsSuccess)
{
HandleApiError(response.Data);
}
return response.Data;
}
var fallbackMessage = GetFriendlyInfrastructureErrorMessage(response);
Snackbar.Add(fallbackMessage, Severity.Error);
return new ApiResponse<T>
{
IsSuccess = false,
StatusCode = (int)response.StatusCode,
Message = fallbackMessage
};
}
catch (Exception ex)
{
var systemError = $"Client System Error: {ex.Message}";
Snackbar.Add(systemError, Severity.Error);
return new ApiResponse<T> { IsSuccess = false, Message = systemError };
}
}
private void HandleApiError<T>(ApiResponse<T> response)
{
var mainMessage = response.Message ?? "Operation failed";
if (response.Errors != null && response.Errors.Any())
{
var combinedErrors = string.Join(Environment.NewLine, response.Errors.Select(e => $"• {e}"));
Snackbar.Add(combinedErrors, Severity.Error, config =>
{
config.ShowCloseIcon = true;
config.VisibleStateDuration = 3000;
});
}
else
{
Snackbar.Add(mainMessage, Severity.Error);
}
}
private string GetFriendlyInfrastructureErrorMessage(RestResponse response)
{
return response.StatusCode switch
{
HttpStatusCode.ServiceUnavailable => "Server is currently under maintenance.",
HttpStatusCode.GatewayTimeout => "Server took too long to respond.",
HttpStatusCode.Unauthorized => "Session expired. Please login again.",
HttpStatusCode.Forbidden => "You do not have permission to access this resource.",
HttpStatusCode.InternalServerError => "A critical error occurred on the server.",
_ => "Unable to reach the server. Please check your connection."
};
}
}