import { notFound } from "next/navigation"; import { prisma } from "@/lib/prisma"; import PartDetailClient from "./PartDetailClient"; export const dynamic = "force-dynamic"; export default async function AdminPartDetailPage({ params, }: { params: Promise<{ id: string; assemblyId: string; partId: string }>; }) { const { id, assemblyId, partId } = await params; const [part, machines, templates] = await Promise.all([ prisma.part.findFirst({ where: { id: partId, assemblyId, assembly: { projectId: id } }, include: { assembly: { select: { id: true, code: true, name: true, project: { select: { id: true, code: true, name: true } }, }, }, stepFile: true, drawingFile: true, cutFile: true, thumbnailFile: true, operations: { orderBy: { sequence: "asc" }, include: { machine: { select: { id: true, name: true } }, template: { select: { id: true, name: true } }, timeLogs: { orderBy: { startedAt: "desc" }, include: { operator: { select: { id: true, name: true } } }, }, }, }, }, }), prisma.machine.findMany({ where: { active: true }, orderBy: { name: "asc" }, select: { id: true, name: true }, }), prisma.operationTemplate.findMany({ where: { active: true }, orderBy: { name: "asc" }, select: { id: true, name: true, machineId: true, defaultSettings: true, defaultInstructions: true, qcRequired: true, }, }), ]); if (!part) notFound(); // QC history across every op on the part — newest first. Same data feeds // two views: the "QC history" strip on the part page and the failure-digest // on the admin dashboard. Keeping it to the last 50 per part is plenty for // any realistic production run. const qcRecords = await prisma.qCRecord.findMany({ where: { operation: { partId: part.id } }, orderBy: { createdAt: "desc" }, take: 50, include: { operator: { select: { id: true, name: true } }, operation: { select: { id: true, sequence: true, name: true } }, }, }); const fileView = (f: typeof part.stepFile) => f ? { id: f.id, originalName: f.originalName, sizeBytes: f.sizeBytes, kind: f.kind, mimeType: f.mimeType, } : null; return ( ({ id: op.id, sequence: op.sequence, name: op.name, kind: op.kind, machineId: op.machineId, machineName: op.machine?.name ?? null, templateId: op.templateId, templateName: op.template?.name ?? null, settings: op.settings, materialNotes: op.materialNotes, instructions: op.instructions, qcRequired: op.qcRequired, plannedMinutes: op.plannedMinutes, plannedUnits: op.plannedUnits, status: op.status, qrToken: op.qrToken, timeLogs: op.timeLogs.map((l) => ({ id: l.id, startedAt: l.startedAt.toISOString(), endedAt: l.endedAt ? l.endedAt.toISOString() : null, unitsProcessed: l.unitsProcessed, note: l.note, operatorName: l.operator.name, })), }))} machines={machines} templates={templates.map((t) => ({ id: t.id, name: t.name, machineId: t.machineId, defaultSettings: t.defaultSettings, defaultInstructions: t.defaultInstructions, qcRequired: t.qcRequired, }))} qcRecords={qcRecords.map((r) => ({ id: r.id, kind: r.kind, passed: r.passed, notes: r.notes, measurements: r.measurements, createdAt: r.createdAt.toISOString(), operatorName: r.operator.name, operationSequence: r.operation.sequence, operationName: r.operation.name, }))} /> ); }