diff --git a/src/app/api/alerts/[id]/route.ts b/src/app/api/alerts/[id]/route.ts new file mode 100644 index 0000000..018435b --- /dev/null +++ b/src/app/api/alerts/[id]/route.ts @@ -0,0 +1,9 @@ +import { NextRequest, NextResponse } from 'next/server' +import { eq } from 'drizzle-orm' +import { db, alerts } from '@/lib/db' + +export async function DELETE(_req: NextRequest, { params }: { params: Promise<{ id: string }> }) { + const { id } = await params + await db.delete(alerts).where(eq(alerts.id, id)) + return NextResponse.json({ ok: true }) +} diff --git a/src/app/api/alerts/route.ts b/src/app/api/alerts/route.ts new file mode 100644 index 0000000..ac4acde --- /dev/null +++ b/src/app/api/alerts/route.ts @@ -0,0 +1,39 @@ +import { NextRequest, NextResponse } from 'next/server' +import { z } from 'zod' +import { db, alerts } from '@/lib/db' + +const CreateSchema = z.object({ + productId: z.string().uuid(), + type: z.enum(['target_price', 'all_time_low', 'percent_drop']), + config: z.record(z.string(), z.unknown()), +}) + +export async function POST(req: NextRequest) { + const body = await req.json() + const parsed = CreateSchema.safeParse(body) + if (!parsed.success) return NextResponse.json({ error: parsed.error.message }, { status: 400 }) + + const cfg = parsed.data.config + switch (parsed.data.type) { + case 'target_price': + if (typeof cfg.threshold !== 'number' || cfg.threshold <= 0) { + return NextResponse.json({ error: 'threshold (number > 0) required' }, { status: 400 }) + } + break + case 'percent_drop': + if (typeof cfg.lookback_days !== 'number' || typeof cfg.percent !== 'number') { + return NextResponse.json({ error: 'lookback_days + percent required' }, { status: 400 }) + } + break + case 'all_time_low': + break + } + + const [inserted] = await db.insert(alerts).values({ + productId: parsed.data.productId, + type: parsed.data.type, + config: parsed.data.config, + }).returning() + + return NextResponse.json(inserted, { status: 201 }) +}