Enhance project setup with Prisma, new scripts, and dependencies; update README for clarity and add API routes; improve layout and styling for better user experience
This commit is contained in:
176
src/app/api/evaluations/[id]/route.ts
Normal file
176
src/app/api/evaluations/[id]/route.ts
Normal file
@@ -0,0 +1,176 @@
|
||||
import { NextRequest, NextResponse } from "next/server";
|
||||
import { Prisma } from "@prisma/client";
|
||||
import { prisma } from "@/lib/db";
|
||||
|
||||
export async function GET(
|
||||
_req: NextRequest,
|
||||
{ params }: { params: Promise<{ id: string }> }
|
||||
) {
|
||||
try {
|
||||
const { id } = await params;
|
||||
const evaluation = await prisma.evaluation.findUnique({
|
||||
where: { id },
|
||||
include: {
|
||||
template: {
|
||||
include: {
|
||||
dimensions: { orderBy: { orderIndex: "asc" } },
|
||||
},
|
||||
},
|
||||
dimensionScores: { include: { dimension: true } },
|
||||
},
|
||||
});
|
||||
|
||||
if (!evaluation) {
|
||||
return NextResponse.json({ error: "Evaluation not found" }, { status: 404 });
|
||||
}
|
||||
|
||||
// Prisma ORM omits suggestedQuestions in some contexts — fetch via raw
|
||||
const templateId = evaluation.templateId;
|
||||
const dimsRaw = evaluation.template
|
||||
? ((await prisma.$queryRaw(
|
||||
Prisma.sql`SELECT id, slug, title, rubric, "orderIndex", "suggestedQuestions" FROM "TemplateDimension" WHERE "templateId" = ${templateId} ORDER BY "orderIndex" ASC`
|
||||
)) as { id: string; slug: string; title: string; rubric: string; orderIndex: number; suggestedQuestions: string | null }[])
|
||||
: [];
|
||||
|
||||
const dimMap = new Map(dimsRaw.map((d) => [d.id, d]));
|
||||
|
||||
const out = {
|
||||
...evaluation,
|
||||
template: evaluation.template
|
||||
? {
|
||||
...evaluation.template,
|
||||
dimensions: evaluation.template.dimensions.map((d) => {
|
||||
const raw = dimMap.get(d.id);
|
||||
return {
|
||||
id: d.id,
|
||||
slug: d.slug,
|
||||
title: d.title,
|
||||
rubric: d.rubric,
|
||||
orderIndex: d.orderIndex,
|
||||
suggestedQuestions: raw?.suggestedQuestions ?? d.suggestedQuestions,
|
||||
};
|
||||
}),
|
||||
}
|
||||
: null,
|
||||
dimensionScores: evaluation.dimensionScores.map((ds) => ({
|
||||
...ds,
|
||||
dimension: ds.dimension
|
||||
? {
|
||||
id: ds.dimension.id,
|
||||
slug: ds.dimension.slug,
|
||||
title: ds.dimension.title,
|
||||
rubric: ds.dimension.rubric,
|
||||
suggestedQuestions: dimMap.get(ds.dimension.id)?.suggestedQuestions ?? ds.dimension.suggestedQuestions,
|
||||
}
|
||||
: null,
|
||||
})),
|
||||
};
|
||||
return NextResponse.json(out);
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
return NextResponse.json({ error: "Failed to fetch evaluation" }, { status: 500 });
|
||||
}
|
||||
}
|
||||
|
||||
export async function PUT(
|
||||
req: NextRequest,
|
||||
{ params }: { params: Promise<{ id: string }> }
|
||||
) {
|
||||
try {
|
||||
const { id } = await params;
|
||||
const body = await req.json();
|
||||
|
||||
const { candidateName, candidateRole, evaluatorName, evaluationDate, status, findings, recommendations, dimensionScores } = body;
|
||||
|
||||
const existing = await prisma.evaluation.findUnique({ where: { id } });
|
||||
if (!existing) {
|
||||
return NextResponse.json({ error: "Evaluation not found" }, { status: 404 });
|
||||
}
|
||||
|
||||
const updateData: Record<string, unknown> = {};
|
||||
if (candidateName != null) updateData.candidateName = candidateName;
|
||||
if (candidateRole != null) updateData.candidateRole = candidateRole;
|
||||
if (evaluatorName != null) updateData.evaluatorName = evaluatorName;
|
||||
if (evaluationDate != null) updateData.evaluationDate = new Date(evaluationDate);
|
||||
if (status != null) updateData.status = status;
|
||||
if (findings != null) updateData.findings = findings;
|
||||
if (recommendations != null) updateData.recommendations = recommendations;
|
||||
|
||||
if (Object.keys(updateData).length > 0) {
|
||||
await prisma.auditLog.create({
|
||||
data: {
|
||||
evaluationId: id,
|
||||
action: "updated",
|
||||
newValue: JSON.stringify(updateData),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
const evaluation = await prisma.evaluation.update({
|
||||
where: { id },
|
||||
data: updateData,
|
||||
include: {
|
||||
template: { include: { dimensions: { orderBy: { orderIndex: "asc" } } } },
|
||||
dimensionScores: { include: { dimension: true } },
|
||||
},
|
||||
});
|
||||
|
||||
if (dimensionScores && Array.isArray(dimensionScores)) {
|
||||
for (const ds of dimensionScores) {
|
||||
if (ds.dimensionId) {
|
||||
await prisma.dimensionScore.upsert({
|
||||
where: {
|
||||
evaluationId_dimensionId: {
|
||||
evaluationId: id,
|
||||
dimensionId: ds.dimensionId,
|
||||
},
|
||||
},
|
||||
update: {
|
||||
score: ds.score,
|
||||
justification: ds.justification,
|
||||
examplesObserved: ds.examplesObserved,
|
||||
confidence: ds.confidence,
|
||||
candidateNotes: ds.candidateNotes,
|
||||
},
|
||||
create: {
|
||||
evaluationId: id,
|
||||
dimensionId: ds.dimensionId,
|
||||
score: ds.score,
|
||||
justification: ds.justification,
|
||||
examplesObserved: ds.examplesObserved,
|
||||
confidence: ds.confidence,
|
||||
candidateNotes: ds.candidateNotes,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const updated = await prisma.evaluation.findUnique({
|
||||
where: { id },
|
||||
include: {
|
||||
template: { include: { dimensions: { orderBy: { orderIndex: "asc" } } } },
|
||||
dimensionScores: { include: { dimension: true } },
|
||||
},
|
||||
});
|
||||
|
||||
return NextResponse.json(updated);
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
return NextResponse.json({ error: "Failed to update evaluation" }, { status: 500 });
|
||||
}
|
||||
}
|
||||
|
||||
export async function DELETE(
|
||||
_req: NextRequest,
|
||||
{ params }: { params: Promise<{ id: string }> }
|
||||
) {
|
||||
try {
|
||||
const { id } = await params;
|
||||
await prisma.evaluation.delete({ where: { id } });
|
||||
return NextResponse.json({ ok: true });
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
return NextResponse.json({ error: "Failed to delete evaluation" }, { status: 500 });
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user