← 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 });
  }
}