0a12cdfbcc
- v1/events GET: offset now clamped ≥0, limit fallback prevents NaN being passed to Prisma take/skip - v1/growth POST: validate date is a valid ISO date before new Date() to avoid Invalid Date silently propagating into DB Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
55 lines
2.4 KiB
TypeScript
55 lines
2.4 KiB
TypeScript
import { NextResponse } from "next/server";
|
|
import { prisma } from "@/lib/prisma";
|
|
import { verifyApiKey, hasScope } from "@/lib/api-auth";
|
|
|
|
export async function GET(req: Request) {
|
|
const ctx = await verifyApiKey(req);
|
|
if (!ctx) return NextResponse.json({ error: "Invalid or missing API key" }, { status: 401 });
|
|
if (!hasScope(ctx, "growth:read")) return NextResponse.json({ error: "Insufficient scope — requires growth:read" }, { status: 403 });
|
|
|
|
const { searchParams } = new URL(req.url);
|
|
const babyId = searchParams.get("babyId");
|
|
if (!babyId) return NextResponse.json({ error: "babyId is required" }, { status: 400 });
|
|
|
|
const baby = await prisma.baby.findFirst({ where: { id: babyId, familyId: ctx.familyId } });
|
|
if (!baby) return NextResponse.json({ error: "Baby not found" }, { status: 404 });
|
|
|
|
const logs = await prisma.growthLog.findMany({
|
|
where: { babyId },
|
|
orderBy: { date: "asc" },
|
|
select: { id: true, date: true, weight: true, height: true, headCirc: true, notes: true, createdAt: true },
|
|
});
|
|
|
|
return NextResponse.json({ logs });
|
|
}
|
|
|
|
export async function POST(req: Request) {
|
|
const ctx = await verifyApiKey(req);
|
|
if (!ctx) return NextResponse.json({ error: "Invalid or missing API key" }, { status: 401 });
|
|
if (!hasScope(ctx, "growth:write")) return NextResponse.json({ error: "Insufficient scope — requires growth:write" }, { status: 403 });
|
|
|
|
const body = await req.json().catch(() => null);
|
|
if (!body) return NextResponse.json({ error: "Invalid JSON body" }, { status: 400 });
|
|
|
|
const { babyId, date, weight, height, headCirc, notes } = body;
|
|
if (!babyId || !date) return NextResponse.json({ error: "babyId and date are required" }, { status: 400 });
|
|
if (isNaN(new Date(date).getTime())) return NextResponse.json({ error: "Invalid date format" }, { status: 400 });
|
|
|
|
const baby = await prisma.baby.findFirst({ where: { id: babyId, familyId: ctx.familyId } });
|
|
if (!baby) return NextResponse.json({ error: "Baby not found" }, { status: 404 });
|
|
|
|
const log = await prisma.growthLog.create({
|
|
data: {
|
|
babyId,
|
|
date: new Date(date),
|
|
weight: weight != null ? Number(weight) : null,
|
|
height: height != null ? Number(height) : null,
|
|
headCirc: headCirc != null ? Number(headCirc) : null,
|
|
notes: notes ?? null,
|
|
},
|
|
select: { id: true, date: true, weight: true, height: true, headCirc: true, notes: true, createdAt: true },
|
|
});
|
|
|
|
return NextResponse.json({ log }, { status: 201 });
|
|
}
|