import { cookies } from 'next/headers' import { notFound } from 'next/navigation' import { getIronSession } from 'iron-session' import { SessionData, sessionOptions } from '@/lib/session' import { prisma } from '@/lib/prisma' import { productAccessFilter } from '@/lib/product-access' import { ideaToDto } from '@/lib/idea-dto' import { IdeaDetailLayout } from '@/components/ideas/idea-detail-layout' import { loadIdeaSyncData } from './sync-tab-server' export const dynamic = 'force-dynamic' interface PageProps { params: Promise<{ id: string }> searchParams: Promise<{ tab?: string }> } export default async function IdeaDetailPage({ params, searchParams }: PageProps) { const session = await getIronSession(await cookies(), sessionOptions) if (!session.userId) notFound() // proxy.ts redirect zou ons al moeten hebben const { id } = await params const { tab } = await searchParams // M12: strikt user_id-only — 404 (niet 403) voor andere users (anti-enum). const idea = await prisma.idea.findFirst({ where: { id, user_id: session.userId }, include: { product: { select: { id: true, name: true, repo_url: true } }, pbi: { select: { id: true, code: true, title: true } }, secondary_products: { include: { product: { select: { id: true, name: true } } } }, }, }) if (!idea) notFound() // Producten voor de "koppel product"-dropdown in de form-tab. const products = await prisma.product.findMany({ where: { ...productAccessFilter(session.userId), archived: false }, orderBy: { name: 'asc' }, select: { id: true, name: true, repo_url: true }, }) // Recent logs (laatste 100) voor de Timeline-tab. const logs = await prisma.ideaLog.findMany({ where: { idea_id: id }, orderBy: { created_at: 'desc' }, take: 100, select: { id: true, type: true, content: true, metadata: true, created_at: true, }, }) // Open vragen voor dit idee — voor de Timeline-tab. const questions = await prisma.claudeQuestion.findMany({ where: { idea_id: id }, orderBy: { created_at: 'desc' }, take: 50, select: { id: true, question: true, options: true, status: true, answer: true, created_at: true, expires_at: true, }, }) const userQuestionsRaw = await prisma.userQuestion.findMany({ where: { idea_id: id }, orderBy: { created_at: 'asc' }, take: 100, select: { id: true, question: true, answer: true, status: true, created_at: true }, }) // Sync-tab data — alleen geladen als idea PLANNED is en pbi_id gevuld. // loadIdeaSyncData past zelf user_id-scope toe en retourneert null als // het idee geen pbi heeft. const syncData = idea.status === 'PLANNED' && idea.pbi_id ? await loadIdeaSyncData(id, session.userId) : null return ( ({ id: l.id, type: l.type, content: l.content, metadata: l.metadata, created_at: l.created_at.toISOString(), }))} questions={questions.map((q) => ({ id: q.id, question: q.question, options: Array.isArray(q.options) ? (q.options as string[]) : null, status: q.status as 'open' | 'answered' | 'cancelled' | 'expired', answer: q.answer ?? null, created_at: q.created_at.toISOString(), expires_at: q.expires_at.toISOString(), }))} userQuestions={userQuestionsRaw.map((uq) => ({ id: uq.id, question: uq.question, answer: uq.answer, status: uq.status as 'pending' | 'answered', created_at: uq.created_at.toISOString(), }))} isDemo={session.isDemo ?? false} initialTab={tab ?? 'idee'} syncData={syncData} /> ) }