/** * Shadow Run Jobs Composable * Fetch and manage shadow run job list */ import { ref, computed } from 'vue' import type { ShadowRunJob, ShadowRunJobFilter } from '../types' export function useShadowRunJobs() { const jobs = ref([]) const isLoading = ref(false) const error = ref(null) const filter = ref({}) // Mock data for demo — replace with actual API call const mockJobs: ShadowRunJob[] = [ { jobId: '893', modelId: '00000000-0000-0000-0000-000000000001', modelName: 'Hawkeye-Alpha (v2.1)', status: 'running', windowStart: '2024-01-02', windowEnd: '2024-09-10', tradingDays: 252, startedAt: '2026-08-11T08:30:00Z', progress: 67, }, { jobId: '892', modelId: '00000000-0000-0000-0000-000000000002', modelName: 'Falcon-Beta (v1.8)', status: 'completed', windowStart: '2024-01-02', windowEnd: '2024-09-10', tradingDays: 252, startedAt: '2026-08-05T10:15:00Z', completedAt: '2026-08-08T14:22:00Z', progress: 100, }, { jobId: '891', modelId: '00000000-0000-0000-0000-000000000003', modelName: 'Eagle-Gamma (v3.0)', status: 'failed', windowStart: '2024-01-02', windowEnd: '2024-09-10', tradingDays: 252, startedAt: '2026-08-03T09:00:00Z', completedAt: '2026-08-03T12:45:00Z', progress: 0, errorMessage: 'Market data fetch timeout (KRX OpenAPI unavailable)', }, ] const filteredJobs = computed(() => { let result = jobs.value if (filter.value.status) { result = result.filter(j => j.status === filter.value.status) } if (filter.value.modelId) { result = result.filter(j => j.modelId === filter.value.modelId) } if (filter.value.search) { const q = filter.value.search.toLowerCase() result = result.filter( j => j.modelName.toLowerCase().includes(q) || j.jobId.includes(q) ) } return result }) const statusStats = computed(() => ({ running: jobs.value.filter(j => j.status === 'running').length, completed: jobs.value.filter(j => j.status === 'completed').length, failed: jobs.value.filter(j => j.status === 'failed').length, total: jobs.value.length, })) async function fetchJobs() { isLoading.value = true error.value = null try { // Simulate API call delay await new Promise(resolve => setTimeout(resolve, 500)) jobs.value = mockJobs } catch (err) { error.value = err instanceof Error ? err.message : 'Failed to fetch jobs' } finally { isLoading.value = false } } function setFilter(newFilter: ShadowRunJobFilter) { filter.value = newFilter } return { jobs, filteredJobs, isLoading, error, statusStats, fetchJobs, setFilter, } }