feat(ui): Blazor WebAssembly 마이그레이션 및 API-First 로그인 구현

This commit is contained in:
2026-07-01 11:22:09 +09:00
parent bdb9262f4e
commit 4de9339163
21 changed files with 246 additions and 80 deletions
@@ -0,0 +1,213 @@
using System.Net.Http.Json;
using System.Text.Json.Serialization;
using QuantEngine.Core.Interfaces;
namespace QuantEngine.Web.Client.Services;
public class ApiClient
{
private readonly HttpClient _http;
private readonly ILogger<ApiClient> _logger;
public ApiClient(HttpClient http, ILogger<ApiClient> logger)
{
_http = http;
_logger = logger;
}
// Collection API Methods
public async Task<CollectionDashboardStateDto?> GetCollectionStateAsync()
{
try
{
return await _http.GetFromJsonAsync<CollectionDashboardStateDto>("api/collection/state");
}
catch (Exception ex)
{
_logger.LogError(ex, "Error fetching collection state");
return null;
}
}
public async Task<CollectionRunsResponse?> GetCollectionRunsAsync(int limit = 20)
{
try
{
return await _http.GetFromJsonAsync<CollectionRunsResponse>($"api/collection/runs?limit={limit}");
}
catch (Exception ex)
{
_logger.LogError(ex, "Error fetching collection runs");
return null;
}
}
public async Task<CollectionRunSnapshotsResponse?> GetCollectionSnapshotsAsync(string runId)
{
try
{
return await _http.GetFromJsonAsync<CollectionRunSnapshotsResponse>($"api/collection/runs/{runId}/snapshots");
}
catch (Exception ex)
{
_logger.LogError(ex, $"Error fetching snapshots for run {runId}");
return null;
}
}
public async Task<CollectionRunErrorsResponse?> GetCollectionErrorsAsync(string runId, int limit = 50)
{
try
{
return await _http.GetFromJsonAsync<CollectionRunErrorsResponse>($"api/collection/runs/{runId}/errors?limit={limit}");
}
catch (Exception ex)
{
_logger.LogError(ex, $"Error fetching errors for run {runId}");
return null;
}
}
public async Task<CollectionRunStartResponse?> StartCollectionRunAsync()
{
try
{
var response = await _http.PostAsJsonAsync("api/collection/run", new { });
if (response.IsSuccessStatusCode)
{
return await response.Content.ReadFromJsonAsync<CollectionRunStartResponse>();
}
return null;
}
catch (Exception ex)
{
_logger.LogError(ex, "Error starting collection run");
return null;
}
}
}
// DTOs
public class CollectionDashboardStateDto
{
[JsonPropertyName("lastRunId")]
public string? LastRunId { get; set; }
[JsonPropertyName("lastRunStatus")]
public string? LastRunStatus { get; set; }
[JsonPropertyName("lastFinishedAt")]
public string? LastFinishedAt { get; set; }
[JsonPropertyName("totalSnapshots")]
public int TotalSnapshots { get; set; }
[JsonPropertyName("totalErrors")]
public int TotalErrors { get; set; }
[JsonPropertyName("recentErrors")]
public List<CollectionErrorDto> RecentErrors { get; set; } = new();
}
public class CollectionRunDto
{
[JsonPropertyName("runId")]
public string RunId { get; set; } = "";
[JsonPropertyName("status")]
public string Status { get; set; } = "";
[JsonPropertyName("startedAt")]
public string StartedAt { get; set; } = "";
[JsonPropertyName("finishedAt")]
public string? FinishedAt { get; set; }
[JsonPropertyName("totalSnapshots")]
public int? TotalSnapshots { get; set; }
[JsonPropertyName("totalErrors")]
public int? TotalErrors { get; set; }
}
public class CollectionSnapshotDto
{
[JsonPropertyName("runId")]
public string RunId { get; set; } = "";
[JsonPropertyName("datasetName")]
public string DatasetName { get; set; } = "";
[JsonPropertyName("ticker")]
public string Ticker { get; set; } = "";
[JsonPropertyName("sourceName")]
public string SourceName { get; set; } = "";
[JsonPropertyName("capturedAt")]
public string CapturedAt { get; set; } = "";
}
public class CollectionErrorDto
{
[JsonPropertyName("runId")]
public string RunId { get; set; } = "";
[JsonPropertyName("sourceName")]
public string SourceName { get; set; } = "";
[JsonPropertyName("errorKind")]
public string ErrorKind { get; set; } = "";
[JsonPropertyName("errorMessage")]
public string ErrorMessage { get; set; } = "";
[JsonPropertyName("ticker")]
public string Ticker { get; set; } = "";
}
public class CollectionRunsResponse
{
[JsonPropertyName("runs")]
public List<CollectionRunDto> Runs { get; set; } = new();
[JsonPropertyName("count")]
public int Count { get; set; }
}
public class CollectionRunSnapshotsResponse
{
[JsonPropertyName("runId")]
public string RunId { get; set; } = "";
[JsonPropertyName("snapshots")]
public List<CollectionSnapshotDto> Snapshots { get; set; } = new();
[JsonPropertyName("count")]
public int Count { get; set; }
}
public class CollectionRunErrorsResponse
{
[JsonPropertyName("runId")]
public string RunId { get; set; } = "";
[JsonPropertyName("errors")]
public List<CollectionErrorDto> Errors { get; set; } = new();
[JsonPropertyName("count")]
public int Count { get; set; }
}
public class CollectionRunStartResponse
{
[JsonPropertyName("runId")]
public string RunId { get; set; } = "";
[JsonPropertyName("status")]
public string Status { get; set; } = "";
[JsonPropertyName("startedAt")]
public string StartedAt { get; set; } = "";
}