refactor(fe): replace custom HTML table with standardized DataGridShell in ShadowRunQueue

This commit is contained in:
2026-08-15 21:16:47 +09:00
parent 7c9095bf8d
commit 95d5ebc14e
@@ -1,8 +1,11 @@
<script setup lang="ts"> <script setup lang="ts">
import { reactive, computed, ref, onMounted } from 'vue' import { reactive, computed, ref, onMounted } from 'vue'
import BatchOperationsPageV2 from '../../../shared/ui/screen-types/v2/BatchOperationsPageV2.vue' import BatchOperationsPageV2 from '../../../shared/ui/screen-types/v2/BatchOperationsPageV2.vue'
import DataGridShell from '../../../shared/ui/DataGridShell.vue'
import { KsButton, KsStatusTag } from '../../../shared/ui/components' import { KsButton, KsStatusTag } from '../../../shared/ui/components'
import type { StandardScreenState } from '../../../shared/ui/contracts/screenContract' import type { StandardScreenState } from '../../../shared/ui/contracts/screenContract'
import type { UiGridColumn } from '../../../shared/ui/adapter/contracts'
import { formatAsOf } from '../../../shared/formatters/financial'
// KBX T08 Governance Audit & Screen State // KBX T08 Governance Audit & Screen State
const screenState = ref<StandardScreenState>('READY') const screenState = ref<StandardScreenState>('READY')
@@ -62,7 +65,7 @@ onMounted(() => {
screenState.value = 'LOADING' screenState.value = 'LOADING'
setTimeout(() => { setTimeout(() => {
screenState.value = 'READY' screenState.value = 'READY'
}, 500) }, 300)
}) })
const filteredJobs = computed(() => { const filteredJobs = computed(() => {
@@ -75,15 +78,15 @@ const filteredJobs = computed(() => {
}) })
}) })
const formatDate = (dateString: string) => { const shadowRunColumns: UiGridColumn[] = [
return new Date(dateString).toLocaleDateString('ko-KR', { { field: 'jobId', header: 'Job ID', width: 90, formatter: value => `#${value}` },
year: 'numeric', { field: 'modelName', header: 'Model Name', minWidth: 160 },
month: '2-digit', { field: 'windowStart', header: 'Window Period', minWidth: 180, formatter: (val, row) => `${val} ~ ${(row as any)?.windowEnd ?? ''}` },
day: '2-digit', { field: 'tradingDays', header: 'Days', width: 80, formatter: val => `${val}d` },
hour: '2-digit', { field: 'status', header: 'Status', width: 110, formatter: val => String(val).toUpperCase() },
minute: '2-digit', { field: 'progress', header: 'Progress', width: 100, formatter: val => `${val}%` },
}) { field: 'startedAt', header: 'Started At', minWidth: 160, formatter: val => val ? formatAsOf(String(val)) : '—' },
} ]
const handleRetry = () => { const handleRetry = () => {
screenState.value = 'LOADING' screenState.value = 'LOADING'
@@ -131,63 +134,15 @@ const handleRetry = () => {
/> />
</template> </template>
<!-- Default Slot: Table List --> <!-- Default Slot: Standardized Grid -->
<div class="content"> <div class="content">
<div class="job-list-container"> <div class="job-list-container">
<h2>Shadow Run Jobs ({{ filteredJobs.length }})</h2> <h2>Shadow Run Jobs ({{ filteredJobs.length }})</h2>
<DataGridShell
<div v-if="filteredJobs.length === 0" class="empty-state" role="status"> :rows="filteredJobs"
No shadow run jobs match your filters. :columns="shadowRunColumns"
</div> empty-message="검색 조건에 맞는 배치 작업이 없습니다."
/>
<div v-else class="table-wrapper">
<table class="grid-table" role="table" aria-label="Shadow Run 작업 목록">
<thead>
<tr role="row">
<th role="columnheader">Job ID</th>
<th role="columnheader">Model</th>
<th role="columnheader">Window Period</th>
<th role="columnheader">Trading Days</th>
<th role="columnheader">Status</th>
<th role="columnheader">Progress</th>
<th role="columnheader">Started At</th>
<th role="columnheader">Actions</th>
</tr>
</thead>
<tbody>
<tr v-for="job in filteredJobs" :key="job.jobId" role="row" class="grid-row">
<td role="cell" class="cell-id ks-financial-number">#{{ job.jobId }}</td>
<td role="cell" class="cell-model">
<strong>{{ job.modelName }}</strong>
</td>
<td role="cell" class="cell-window ks-financial-number">
{{ job.windowStart }} ~ {{ job.windowEnd }}
</td>
<td role="cell" class="cell-days ks-financial-number">{{ job.tradingDays }}d</td>
<td role="cell" class="cell-status">
<KsStatusTag
:value="job.status.toUpperCase()"
:severity="job.status === 'completed' ? 'success' : job.status === 'failed' ? 'danger' : 'info'"
/>
</td>
<td role="cell" class="cell-progress">
<div class="progress-bar" role="progressbar" :aria-valuenow="job.progress" aria-valuemin="0" aria-valuemax="100">
<div class="progress-fill" :style="{ width: `${job.progress}%` }"></div>
</div>
<span class="progress-text ks-financial-number">{{ job.progress }}%</span>
</td>
<td role="cell" class="cell-date ks-financial-number">{{ formatDate(job.startedAt) }}</td>
<td role="cell" class="cell-actions">
<KsButton
label="View Logs"
variant="secondary"
size="sm"
/>
</td>
</tr>
</tbody>
</table>
</div>
</div> </div>
</div> </div>
</BatchOperationsPageV2> </BatchOperationsPageV2>