← back to Norma

app/api/pulse/petitions/[id]/route.ts

56 lines

import { NextRequest, NextResponse } from 'next/server';
import { query } from '@/lib/db';

type RouteContext = { params: Promise<{ id: string }> };

/**
 * GET /api/pulse/petitions/[id]
 * PUBLIC API — No auth required.
 * Returns a single active petition by ID.
 */
export async function GET(request: NextRequest, context: RouteContext) {
  const { id } = await context.params;

  // Validate UUID format
  const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
  if (!uuidRegex.test(id)) {
    return NextResponse.json({ error: 'Invalid petition ID' }, { status: 400 });
  }

  try {
    const result = await query(
      `SELECT id, title, COALESCE(body, description) AS body, description, target, category,
              tags, signature_count, signature_goal, is_featured, talking_points, created_at, updated_at
       FROM petitions
       WHERE id = $1 AND status = 'active'`,
      [id]
    );

    if (result.rowCount === 0) {
      return NextResponse.json({ error: 'Petition not found' }, { status: 404 });
    }

    // Also fetch related petitions (same category, excluding self)
    const petition = result.rows[0];
    const related = await query(
      `SELECT id, title, COALESCE(body, description) AS body, category, signature_count, signature_goal, is_featured
       FROM petitions
       WHERE status = 'active' AND category = $1 AND id != $2
       ORDER BY COALESCE(signature_count, 0) DESC
       LIMIT 3`,
      [petition.category, id]
    );

    return NextResponse.json({
      petition,
      related: related.rows,
    });
  } catch (err) {
    console.error('[api/pulse/petitions/[id]] GET error:', (err as Error).message);
    return NextResponse.json(
      { error: 'Failed to fetch petition' },
      { status: 500 }
    );
  }
}