enhancment complete with phase 10

This commit is contained in:
dimitar committed 2026-03-10 05:37:22 +01:00
1 parent 2c4927478a
commit 6adb541967
44 files changed
+7820 -845

No files matched your search

@@ -2,19 +2,23 @@ import { NextRequest, NextResponse } from "next/server";
import { auth } from "@clerk/nextjs/server";
import { getDatabase } from "@/lib/database";
import log from "@/lib/logger";
// Helper to add CORS headers
function corsHeaders() {
return {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, OPTIONS",
"Access-Control-Allow-Headers": "Content-Type, Authorization",
};
}
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: corsHeaders() });
return NextResponse.json({}, { headers: addCorsHeaders() });
}
// GET - Get specific goal
@@ -25,10 +29,7 @@ export async function GET(
try {
const { userId } = await auth();
if (!userId) {
return NextResponse.json(
{ error: "Unauthorized" },
{ status: 401, headers: corsHeaders() },
);
return unauthorizedResponse(undefined, addCorsHeaders());
}
const { id } = await params;
@@ -37,27 +38,18 @@ export async function GET(
const goal = await db.getFitnessGoalById(id);
if (!goal) {
return NextResponse.json(
{ error: "Goal not found" },
{ status: 404, headers: corsHeaders() },
);
return notFoundResponse("Goal not found", addCorsHeaders());
}
// Verify ownership
if (goal.userId !== userId) {
return NextResponse.json(
{ error: "Forbidden" },
{ status: 403, headers: corsHeaders() },
);
return forbiddenResponse(undefined, addCorsHeaders());
}
return NextResponse.json(goal, { headers: corsHeaders() });
return successResponse(goal, { headers: addCorsHeaders() });
} catch (error) {
log.error("Failed to fetch fitness goal", error);
return NextResponse.json(
{ error: "Internal server error" },
{ status: 500, headers: corsHeaders() },
);
return internalErrorResponse(undefined, addCorsHeaders());
}
}
@@ -69,10 +61,7 @@ export async function PUT(
try {
const { userId } = await auth();
if (!userId) {
return NextResponse.json(
{ error: "Unauthorized" },
{ status: 401, headers: corsHeaders() },
);
return unauthorizedResponse(undefined, addCorsHeaders());
}
const { id } = await params;
@@ -81,34 +70,36 @@ export async function PUT(
// Verify goal exists and user owns it
const existingGoal = await db.getFitnessGoalById(id);
if (!existingGoal) {
return NextResponse.json(
{ error: "Goal not found" },
{ status: 404, headers: corsHeaders() },
);
return notFoundResponse("Goal not found", addCorsHeaders());
}
if (existingGoal.userId !== userId) {
return NextResponse.json(
{ error: "Forbidden" },
{ status: 403, headers: corsHeaders() },
);
return forbiddenResponse(undefined, addCorsHeaders());
}
const updates = await req.json();
// Validate request body
const validation = await validateRequestBody(req, fitnessGoalUpdateSchema);
// Don't allow changing userId or id
delete updates.userId;
delete updates.id;
delete updates.createdAt;
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 NextResponse.json(updatedGoal, { headers: corsHeaders() });
return successResponse(updatedGoal, { headers: addCorsHeaders() });
} catch (error) {
log.error("Failed to update fitness goal", error);
return NextResponse.json(
{ error: "Internal server error" },
{ status: 500, headers: corsHeaders() },
);
return internalErrorResponse(undefined, addCorsHeaders());
}
}
@@ -120,10 +111,7 @@ export async function DELETE(
try {
const { userId } = await auth();
if (!userId) {
return NextResponse.json(
{ error: "Unauthorized" },
{ status: 401, headers: corsHeaders() },
);
return unauthorizedResponse(undefined, addCorsHeaders());
}
const { id } = await params;
@@ -132,33 +120,21 @@ export async function DELETE(
// Verify goal exists and user owns it
const existingGoal = await db.getFitnessGoalById(id);
if (!existingGoal) {
return NextResponse.json(
{ error: "Goal not found" },
{ status: 404, headers: corsHeaders() },
);
return notFoundResponse("Goal not found", addCorsHeaders());
}
if (existingGoal.userId !== userId) {
return NextResponse.json(
{ error: "Forbidden" },
{ status: 403, headers: corsHeaders() },
);
return forbiddenResponse(undefined, addCorsHeaders());
}
const deleted = await db.deleteFitnessGoal(id);
if (deleted) {
return NextResponse.json({ success: true }, { headers: corsHeaders() });
return successResponse({ deleted: true }, { headers: addCorsHeaders() });
} else {
return NextResponse.json(
{ error: "Failed to delete goal" },
{ status: 500, headers: corsHeaders() },
);
return internalErrorResponse("Failed to delete goal", addCorsHeaders());
}
} catch (error) {
log.error("Failed to delete fitness goal", error);
return NextResponse.json(
{ error: "Internal server error" },
{ status: 500, headers: corsHeaders() },
);
return internalErrorResponse(undefined, addCorsHeaders());
}
}