← back to Norma
app/api/outreach-templates/route.ts
88 lines
import { NextRequest, NextResponse } from 'next/server';
import { query } from '@/lib/db';
import { requireRole } from '@/lib/require-role';
/**
* GET /api/outreach-templates?type=meeting_request|phone_script|follow_up|thank_you|one_pager|briefing&limit=&offset=
* List templates, optionally filtered by template_type. Supports pagination.
*/
export async function GET(request: NextRequest) {
const auth = requireRole(request, 'admin', 'staff');
if (auth instanceof NextResponse) return auth;
const { searchParams } = new URL(request.url);
const tType = searchParams.get('type');
let limit = parseInt(searchParams.get('limit') || '50', 10);
if (isNaN(limit) || limit < 1) limit = 50;
if (limit > 200) limit = 200;
let offset = parseInt(searchParams.get('offset') || '0', 10);
if (isNaN(offset) || offset < 0) offset = 0;
const conditions: string[] = [];
const params: unknown[] = [];
let idx = 1;
if (tType) {
conditions.push(`template_type = $${idx++}`);
params.push(tType);
}
const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(' AND ')}` : '';
try {
const countResult = await query(
`SELECT COUNT(*)::int AS total FROM outreach_templates ${whereClause}`,
params
);
const total = countResult.rows[0]?.total ?? 0;
const { rows } = await query(
`SELECT * FROM outreach_templates ${whereClause}
ORDER BY template_type, created_at ASC
LIMIT $${idx} OFFSET $${idx + 1}`,
[...params, limit, offset]
);
return NextResponse.json({ templates: rows, total, limit, offset });
} catch (err) {
return NextResponse.json({ error: (err as Error).message }, { status: 500 });
}
}
/**
* POST /api/outreach-templates
* Create a custom template.
*/
export async function POST(request: NextRequest) {
const auth = requireRole(request, 'admin', 'staff');
if (auth instanceof NextResponse) return auth;
try {
const body = await request.json();
const { template_type, name, subject, body: templateBody, variables, compliance_safe, org_type_safe } = body;
if (!template_type || !name || !templateBody) {
return NextResponse.json({ error: 'template_type, name, and body are required' }, { status: 400 });
}
const { rows } = await query(
`INSERT INTO outreach_templates (template_type, name, subject, body, variables, compliance_safe, org_type_safe)
VALUES ($1, $2, $3, $4, $5, $6, $7) RETURNING *`,
[
template_type,
name,
subject || null,
templateBody,
variables || [],
compliance_safe !== undefined ? compliance_safe : true,
org_type_safe || ['501c3', '501c4'],
]
);
return NextResponse.json({ success: true, template: rows[0] }, { status: 201 });
} catch (err) {
return NextResponse.json({ error: (err as Error).message }, { status: 500 });
}
}