'use server' import { prisma } from '@/lib/prisma' import { getSession } from '@/lib/auth' import type { ClaudeJobKind, ClaudeJobStatus, VerifyResult } from '@prisma/client' export type JobWithRelations = { id: string kind: ClaudeJobKind status: ClaudeJobStatus taskCode: string | null taskTitle: string | null ideaCode: string | null ideaTitle: string | null sprintGoal: string | null sprintCode: string | null productName: string modelId: string | null inputTokens: number | null outputTokens: number | null cacheReadTokens: number | null cacheWriteTokens: number | null branch: string | null prUrl: string | null error: string | null summary: string | null verifyResult: VerifyResult | null startedAt: Date | null finishedAt: Date | null createdAt: Date sprintRunId: string | null } const JOB_INCLUDE = { task: { select: { code: true, title: true } }, idea: { select: { code: true, title: true } }, product: { select: { name: true } }, sprint_run: { include: { sprint: { select: { sprint_goal: true } } } }, } as const function mapJob(j: { id: string kind: ClaudeJobKind status: ClaudeJobStatus model_id: string | null input_tokens: number | null output_tokens: number | null cache_read_tokens: number | null cache_write_tokens: number | null branch: string | null pr_url: string | null error: string | null summary: string | null verify_result: VerifyResult | null started_at: Date | null finished_at: Date | null created_at: Date sprint_run_id: string | null task: { code: string | null; title: string } | null idea: { code: string | null; title: string } | null product: { name: string } sprint_run: { sprint: { sprint_goal: string } } | null }): JobWithRelations { return { id: j.id, kind: j.kind, status: j.status, taskCode: j.task?.code ?? null, taskTitle: j.task?.title ?? null, ideaCode: j.idea?.code ?? null, ideaTitle: j.idea?.title ?? null, sprintGoal: j.sprint_run?.sprint.sprint_goal ?? null, sprintCode: null, productName: j.product.name, modelId: j.model_id, inputTokens: j.input_tokens, outputTokens: j.output_tokens, cacheReadTokens: j.cache_read_tokens, cacheWriteTokens: j.cache_write_tokens, branch: j.branch, prUrl: j.pr_url, error: j.error, summary: j.summary, verifyResult: j.verify_result, startedAt: j.started_at, finishedAt: j.finished_at, createdAt: j.created_at, sprintRunId: j.sprint_run_id, } } export async function fetchJobsPageData(): Promise<{ activeJobs: JobWithRelations[]; doneJobs: JobWithRelations[] } | null> { const session = await getSession() if (!session.userId) return null const [active, done] = await Promise.all([ prisma.claudeJob.findMany({ where: { user_id: session.userId, status: { notIn: ['DONE'] } }, include: JOB_INCLUDE, orderBy: { created_at: 'asc' }, }), prisma.claudeJob.findMany({ where: { user_id: session.userId, status: 'DONE' }, include: JOB_INCLUDE, orderBy: { finished_at: 'desc' }, take: 100, }), ]) return { activeJobs: active.map(mapJob), doneJobs: done.map(mapJob), } }