Files
fitaiProto/apps/admin/src/app/api/fitness-goals/[id]/route.ts
T

141 lines
3.9 KiB
TypeScript

import { NextRequest, NextResponse } from "next/server";
import { auth } from "@clerk/nextjs/server";
import { getDatabase } from "@/lib/database";
import log from "@/lib/logger";
import { fitnessGoalUpdateSchema } from "@/lib/validation/schemas";
import {
validateRequestBody,
validationErrorResponse,
} from "@/lib/validation/helpers";
import {
successResponse,
unauthorizedResponse,
notFoundResponse,
forbiddenResponse,
internalErrorResponse,
addCorsHeaders,
} from "@/lib/api/responses";
// OPTIONS - Handle preflight requests
export async function OPTIONS() {
return NextResponse.json({}, { headers: addCorsHeaders() });
}
// GET - Get specific goal
export async function GET(
req: NextRequest,
{ params }: { params: Promise<{ id: string }> },
) {
try {
const { userId } = await auth();
if (!userId) {
return unauthorizedResponse(undefined, addCorsHeaders());
}
const { id } = await params;
const db = await getDatabase();
const goal = await db.getFitnessGoalById(id);
if (!goal) {
return notFoundResponse("Goal not found", addCorsHeaders());
}
// Verify ownership
if (goal.userId !== userId) {
return forbiddenResponse(undefined, addCorsHeaders());
}
return successResponse(goal, { headers: addCorsHeaders() });
} catch (error) {
log.error("Failed to fetch fitness goal", error);
return internalErrorResponse(undefined, addCorsHeaders());
}
}
// PUT - Update goal
export async function PUT(
req: NextRequest,
{ params }: { params: Promise<{ id: string }> },
) {
try {
const { userId } = await auth();
if (!userId) {
return unauthorizedResponse(undefined, addCorsHeaders());
}
const { id } = await params;
const db = await getDatabase();
// Verify goal exists and user owns it
const existingGoal = await db.getFitnessGoalById(id);
if (!existingGoal) {
return notFoundResponse("Goal not found", addCorsHeaders());
}
if (existingGoal.userId !== userId) {
return forbiddenResponse(undefined, addCorsHeaders());
}
// Validate request body
const validation = await validateRequestBody(req, fitnessGoalUpdateSchema);
if (!validation.success) {
log.warn("Fitness goal update validation failed", {
errors: validation.errors,
});
return validationErrorResponse(validation.errors);
}
// Transform targetDate from string to Date if present
const updates = {
...validation.data,
targetDate: validation.data.targetDate
? new Date(validation.data.targetDate)
: undefined,
};
const updatedGoal = await db.updateFitnessGoal(id, updates);
return successResponse(updatedGoal, { headers: addCorsHeaders() });
} catch (error) {
log.error("Failed to update fitness goal", error);
return internalErrorResponse(undefined, addCorsHeaders());
}
}
// DELETE - Delete goal
export async function DELETE(
req: NextRequest,
{ params }: { params: Promise<{ id: string }> },
) {
try {
const { userId } = await auth();
if (!userId) {
return unauthorizedResponse(undefined, addCorsHeaders());
}
const { id } = await params;
const db = await getDatabase();
// Verify goal exists and user owns it
const existingGoal = await db.getFitnessGoalById(id);
if (!existingGoal) {
return notFoundResponse("Goal not found", addCorsHeaders());
}
if (existingGoal.userId !== userId) {
return forbiddenResponse(undefined, addCorsHeaders());
}
const deleted = await db.deleteFitnessGoal(id);
if (deleted) {
return successResponse({ deleted: true }, { headers: addCorsHeaders() });
} else {
return internalErrorResponse("Failed to delete goal", addCorsHeaders());
}
} catch (error) {
log.error("Failed to delete fitness goal", error);
return internalErrorResponse(undefined, addCorsHeaders());
}
}