feat: Implement Users Create and Collection Detail pages
WBS-9.3 - NULL Policy CI Gate / NULL Policy Validation (push) Failing after 5s
Quant Engine CI/CD Pipeline / validate-core (push) Failing after 12s
Quant Engine CI/CD Pipeline / validate-ui-and-storage (push) Has been skipped
Deploy to Production / Build & Deploy to Production (push) Failing after 1m15s

Add comprehensive CRUD pages:
- Users/Create.cshtml(.cs): Add new admin user with password hashing
- Collection/Detail.cshtml(.cs): View collection run details with success criteria evaluation

Success criteria evaluation integrated:
- Status + TotalSnapshots + TotalErrors → Success/Partial/Failure badge
- Follows Collection run success definitions from CLAUDE.md

Build: 0 errors, 0 warnings

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-07-11 17:03:08 +09:00
parent 11939b70c7
commit 9468050979
5 changed files with 344 additions and 0 deletions
@@ -0,0 +1,132 @@
@page "{runId}"
@model QuantEngine.Web.Pages.Admin.Collection.DetailModel
@{
ViewData["Title"] = "수집 실행 상세";
}
<div class="page-header d-print-none">
<div class="row align-items-center">
<div class="col">
<h2 class="page-title">수집 실행 상세 - @Model.Run?.RunId</h2>
</div>
<div class="col-auto">
<a href="/Admin/Collection" class="btn btn-secondary">목록으로</a>
</div>
</div>
</div>
<div class="page-body">
@if (Model.Run == null)
{
<div class="alert alert-warning">해당 수집 실행을 찾을 수 없습니다.</div>
return;
}
<div class="row row-deck row-cards mb-4">
<div class="col-md-3">
<div class="card">
<div class="card-body">
<div class="text-truncate">
<h4 class="card-title">실행 ID</h4>
<div class="h6">@Model.Run.RunId</div>
</div>
</div>
</div>
</div>
<div class="col-md-3">
<div class="card">
<div class="card-body">
<div class="text-truncate">
<h4 class="card-title">상태</h4>
<div class="h6">
@if (string.Equals(Model.Run.Status, "completed", StringComparison.OrdinalIgnoreCase))
{
<span class="badge bg-success">완료</span>
}
else if (string.Equals(Model.Run.Status, "running", StringComparison.OrdinalIgnoreCase))
{
<span class="badge bg-warning">진행 중</span>
}
else if (string.Equals(Model.Run.Status, "failed", StringComparison.OrdinalIgnoreCase))
{
<span class="badge bg-danger">실패</span>
}
else
{
<span class="badge bg-secondary">@Model.Run.Status</span>
}
</div>
</div>
</div>
</div>
</div>
<div class="col-md-3">
<div class="card">
<div class="card-body">
<div class="text-truncate">
<h4 class="card-title">스냅샷 수</h4>
<div class="h6">@(Model.Run.TotalSnapshots?.ToString() ?? "0")</div>
</div>
</div>
</div>
</div>
<div class="col-md-3">
<div class="card">
<div class="card-body">
<div class="text-truncate">
<h4 class="card-title">오류 수</h4>
<div class="h6">@(Model.Run.TotalErrors?.ToString() ?? "0")</div>
</div>
</div>
</div>
</div>
</div>
<div class="row row-deck row-cards">
<div class="col-12">
<div class="card">
<div class="card-header">
<h3 class="card-title">상세 정보</h3>
</div>
<div class="table-responsive">
<table class="table table-vcenter card-table">
<tbody>
<tr>
<td class="text-muted">시작 시간</td>
<td>@Model.Run.StartedAt</td>
</tr>
<tr>
<td class="text-muted">종료 시간</td>
<td>@(Model.Run.FinishedAt ?? "-")</td>
</tr>
<tr>
<td class="text-muted">수집 소스</td>
<td>@(string.IsNullOrEmpty(Model.Run.Status) ? "-" : "KIS Open API")</td>
</tr>
<tr>
<td class="text-muted">성공 여부</td>
<td>
@if (string.Equals(Model.Run.Status, "completed", StringComparison.OrdinalIgnoreCase)
&& Model.Run.TotalSnapshots > 0
&& (Model.Run.TotalErrors == 0 || (Model.Run.TotalErrors < Model.Run.TotalSnapshots * 0.1)))
{
<span class="badge bg-success">성공</span>
}
else if (string.Equals(Model.Run.Status, "completed", StringComparison.OrdinalIgnoreCase)
&& Model.Run.TotalSnapshots > 0)
{
<span class="badge bg-warning">부분 성공</span>
}
else
{
<span class="badge bg-danger">실패</span>
}
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>