From f4f02bd0d2d5887abc5cd647adc1364d554bac51 Mon Sep 17 00:00:00 2001 From: Madhura68 Date: Wed, 6 May 2026 00:18:21 +0200 Subject: [PATCH] feat(T-561): loadIdeaSyncData server-loader voor Sync-tab MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Joint Idea → PBI → Stories → Tasks → ClaudeJobs + StoryLog in één prisma.findFirst-call. user_id-scope conform M12-keuze 2 (strikt user_id-only). Filtert ClaudeJob op kind=TASK_IMPLEMENTATION en neemt laatste 20 story-logs per story. Returns null als idea geen pbi_id heeft — caller render geen tab. Co-Authored-By: Claude Opus 4.7 (1M context) --- app/(app)/ideas/[id]/sync-tab-server.ts | 85 +++++++++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 app/(app)/ideas/[id]/sync-tab-server.ts diff --git a/app/(app)/ideas/[id]/sync-tab-server.ts b/app/(app)/ideas/[id]/sync-tab-server.ts new file mode 100644 index 0000000..ae93465 --- /dev/null +++ b/app/(app)/ideas/[id]/sync-tab-server.ts @@ -0,0 +1,85 @@ +import 'server-only' +import { prisma } from '@/lib/prisma' + +// Server-only loader voor de Sync-tab op /ideas/[id]. +// Joint Idea → PBI → Stories → Tasks → ClaudeJobs + StoryLog. +// Auth-scope: strikt user_id-only conform M12-keuze 2. +// +// Returns null wanneer: +// - idea bestaat niet of behoort niet aan user +// - idea heeft geen pbi_id (status !== PLANNED, dus sync-tab niet relevant) +// +// Caller (page.tsx) moet de tab niet renderen als deze null retourneert. +export async function loadIdeaSyncData(ideaId: string, userId: string) { + const idea = await prisma.idea.findFirst({ + where: { id: ideaId, user_id: userId }, + select: { + id: true, + code: true, + title: true, + status: true, + pbi_id: true, + product: { select: { id: true, name: true, repo_url: true } }, + pbi: { + select: { + id: true, + code: true, + title: true, + pr_url: true, + pr_merged_at: true, + stories: { + orderBy: { sort_order: 'asc' }, + select: { + id: true, + code: true, + title: true, + status: true, + tasks: { + orderBy: { sort_order: 'asc' }, + select: { + id: true, + code: true, + title: true, + status: true, + claude_jobs: { + where: { kind: 'TASK_IMPLEMENTATION' }, + orderBy: { created_at: 'desc' }, + select: { + id: true, + status: true, + branch: true, + pushed_at: true, + pr_url: true, + error: true, + summary: true, + created_at: true, + finished_at: true, + }, + }, + }, + }, + logs: { + orderBy: { created_at: 'desc' }, + take: 20, + select: { + id: true, + type: true, + content: true, + status: true, + commit_hash: true, + commit_message: true, + created_at: true, + }, + }, + }, + }, + }, + }, + }, + }) + + if (!idea || !idea.pbi) return null + return idea +} + +export type IdeaSyncData = NonNullable>>