← back to Freddy
app/api/funding/route.ts
60 lines
import { NextRequest, NextResponse } from 'next/server';
import { query } from '@/lib/db';
import { verifyAuth } from '@/lib/auth';
import { auditLog } from '@/lib/audit';
export async function GET(request: NextRequest) {
const user = verifyAuth(request);
if (!user) {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
}
try {
const result = await query(`
SELECT fr.id, fr.title, fr.total_pool, fr.allocated, fr.remaining,
fr.status, fr.opens_at, fr.closes_at, fr.cause_filter,
fr.created_at, fr.updated_at,
g.name as granter_name, g.id as granter_id
FROM funding_rounds fr
JOIN granters g ON g.id = fr.granter_id
ORDER BY fr.created_at DESC
LIMIT 50
`);
return NextResponse.json({ funding_rounds: result.rows });
} catch (err) {
console.error('[funding] GET error:', (err as Error).message);
return NextResponse.json({ error: 'Failed to fetch funding rounds' }, { status: 500 });
}
}
export async function POST(request: NextRequest) {
const user = verifyAuth(request);
if (!user) {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
}
try {
const body = await request.json();
const { title, granter_id, total_pool, opens_at, closes_at, cause_filter } = body;
if (!title || !granter_id || !total_pool) {
return NextResponse.json({ error: 'title, granter_id, and total_pool are required' }, { status: 400 });
}
const result = await query(
`INSERT INTO funding_rounds (title, granter_id, total_pool, remaining, opens_at, closes_at, cause_filter)
VALUES ($1, $2, $3, $3, $4, $5, $6)
RETURNING *`,
[title, granter_id, total_pool, opens_at || null, closes_at || null, cause_filter || []],
);
await auditLog('funding_round.created', 'funding_round', result.rows[0].id, { title, user });
return NextResponse.json({ funding_round: result.rows[0] }, { status: 201 });
} catch (err) {
console.error('[funding] POST error:', (err as Error).message);
return NextResponse.json({ error: 'Failed to create funding round' }, { status: 500 });
}
}