import { getCurrentUser } from "@/lib/auth"; import { prisma } from "@/lib/prisma"; import { NextRequest, NextResponse } from "next/server"; import { z } from "zod"; /** * GET /api/exercises/[id] * Get exercise with history */ export async function GET( _request: NextRequest, { params }: { params: { id: string } } ) { try { const user = await getCurrentUser(); if (!user) { return NextResponse.json({ error: "Unauthorized" }, { status: 401 }); } const exercise = await prisma.exercise.findFirst({ where: { id: params.id, userId: user.id, }, }); if (!exercise) { return NextResponse.json({ error: "Exercise not found" }, { status: 404 }); } // Get exercise history grouped by workout const setLogs = await prisma.setLog.findMany({ where: { exerciseId: params.id, workout: { userId: user.id, }, }, include: { workout: { select: { id: true, date: true, name: true, }, }, }, orderBy: [ { workout: { date: "desc" } }, { setNumber: "asc" }, ], take: 100, }); // Group by workout const workoutMap = new Map(); for (const log of setLogs) { const key = log.workoutId; if (!workoutMap.has(key)) { workoutMap.set(key, { workout: log.workout, sets: [] }); } workoutMap.get(key)!.sets.push(log); } const history = Array.from(workoutMap.values()).slice(0, 20); return NextResponse.json({ exercise, history, }); } catch (error) { console.error("GET /api/exercises/[id] error:", error); return NextResponse.json( { error: "Internal server error" }, { status: 500 } ); } } /** * PATCH /api/exercises/[id] * Edit exercise details */ const updateExerciseSchema = z.object({ name: z.string().min(1).optional(), type: z.string().min(1).optional(), muscleGroups: z.array(z.string()).optional(), description: z.string().optional(), inputFields: z.array(z.string().min(1)).optional(), defaultWeightUnit: z.string().nullable().optional(), }); export async function PATCH( request: NextRequest, { params }: { params: { id: string } } ) { try { const user = await getCurrentUser(); if (!user) { return NextResponse.json({ error: "Unauthorized" }, { status: 401 }); } const exercise = await prisma.exercise.findFirst({ where: { id: params.id, userId: user.id, }, }); if (!exercise) { return NextResponse.json({ error: "Exercise not found" }, { status: 404 }); } const body = await request.json(); const validated = updateExerciseSchema.parse(body); const data: any = {}; if (validated.name !== undefined) data.name = validated.name; if (validated.type !== undefined) data.type = validated.type; if (validated.description !== undefined) data.description = validated.description; if (validated.muscleGroups !== undefined) data.muscleGroups = JSON.stringify(validated.muscleGroups); if (validated.inputFields !== undefined) data.inputFields = JSON.stringify(validated.inputFields); if (validated.defaultWeightUnit !== undefined) data.defaultWeightUnit = validated.defaultWeightUnit; const updated = await prisma.exercise.update({ where: { id: params.id }, data, }); return NextResponse.json(updated); } catch (error) { if (error instanceof z.ZodError) { return NextResponse.json( { error: "Invalid data", details: error.errors }, { status: 400 } ); } console.error("PATCH /api/exercises/[id] error:", error); return NextResponse.json( { error: "Internal server error" }, { status: 500 } ); } } /** * DELETE /api/exercises/[id] */ export async function DELETE( _request: NextRequest, { params }: { params: { id: string } } ) { try { const user = await getCurrentUser(); if (!user) { return NextResponse.json({ error: "Unauthorized" }, { status: 401 }); } const exercise = await prisma.exercise.findFirst({ where: { id: params.id, userId: user.id, }, }); if (!exercise) { return NextResponse.json({ error: "Exercise not found" }, { status: 404 }); } await prisma.setLog.deleteMany({ where: { exerciseId: params.id }, }); await prisma.exercise.delete({ where: { id: params.id }, }); return NextResponse.json({ message: "Exercise deleted successfully" }); } catch (error) { console.error("DELETE /api/exercises/[id] error:", error); return NextResponse.json( { error: "Internal server error" }, { status: 500 } ); } }