import { NextRequest, NextResponse } from 'next/server'; import { db } from '@/lib/db'; import { spanAnnotations } from '@/lib/db/schema'; import { eq, desc } from 'drizzle-orm'; // GET - List all span annotations for a chart export async function GET(request: NextRequest) { try { const { searchParams } = request.nextUrl; const chartId = searchParams.get('chartId'); if (!chartId) { return NextResponse.json( { error: 'chartId parameter is required' }, { status: 400 } ); } const spans = await db .select() .from(spanAnnotations) .where(eq(spanAnnotations.chart_id, parseInt(chartId))) .orderBy(desc(spanAnnotations.start_time)); return NextResponse.json(spans); } catch (error) { console.error('Error fetching span annotations:', error); return NextResponse.json( { error: 'Failed to fetch span annotations' }, { status: 500 } ); } } // POST - Create new span annotation export async function POST(request: NextRequest) { try { const body = await request.json(); const { chart_id, start_time, end_time, label, confidence, outcome, notes, sub_spans, color, source, model_prediction, } = body; if (!chart_id || start_time === undefined || end_time === undefined || !label) { return NextResponse.json( { error: 'chart_id, start_time, end_time, and label are required' }, { status: 400 } ); } // Ensure start_time <= end_time (swap if needed) const actualStartTime = Math.min(start_time, end_time); const actualEndTime = Math.max(start_time, end_time); const result = await db .insert(spanAnnotations) .values({ chart_id, start_time: actualStartTime, end_time: actualEndTime, label, confidence: confidence || null, outcome: outcome || null, notes: notes || null, sub_spans: sub_spans || null, color: color || '#2196F3', source: source || 'human', // 'human', 'model', or 'human_correction' model_prediction: model_prediction || null, }) .returning(); return NextResponse.json(result[0], { status: 201 }); } catch (error: any) { console.error('Error creating span annotation:', error); return NextResponse.json( { error: 'Failed to create span annotation' }, { status: 500 } ); } }