← back to Norma
app/api/pulse/activity/route.ts
74 lines
import { NextRequest, NextResponse } from 'next/server';
import { query } from '@/lib/db';
import { requireRole } from '@/lib/require-role';
import type { AuthSession } from '@/lib/auth';
/**
* GET /api/pulse/activity
* Returns the authenticated user's signature history with petition details.
* Requires any authenticated role (admin, staff, pulse).
*
* Query params:
* ?page=1 — page number (default 1)
* ?limit=20 — results per page (default 20, max 100)
*/
export async function GET(request: NextRequest) {
const result = requireRole(request, 'admin', 'staff', 'pulse');
if (result instanceof NextResponse) return result;
const session = result as AuthSession;
try {
const { searchParams } = new URL(request.url);
let page = parseInt(searchParams.get('page') || '1', 10);
if (isNaN(page) || page < 1) page = 1;
let limit = parseInt(searchParams.get('limit') || '20', 10);
if (isNaN(limit) || limit < 1) limit = 20;
if (limit > 100) limit = 100;
const offset = (page - 1) * limit;
// Count total signatures by this user
const countRes = await query(
`SELECT COUNT(*)::int AS total
FROM petition_signatures
WHERE signed_by_username = $1`,
[session.username],
);
const total = countRes.rows[0]?.total ?? 0;
// Fetch signatures with petition details
const dataRes = await query(
`SELECT
ps.id AS signature_id,
ps.signed_at,
ps.comment,
p.id AS petition_id,
p.title AS petition_title,
p.category,
p.status,
p.signature_count,
p.signature_goal,
p.is_featured
FROM petition_signatures ps
JOIN petitions p ON p.id = ps.petition_id
WHERE ps.signed_by_username = $1
ORDER BY ps.signed_at DESC
LIMIT $2 OFFSET $3`,
[session.username, limit, offset],
);
return NextResponse.json({
activity: dataRes.rows,
total,
page,
limit,
totalPages: Math.ceil(total / limit),
});
} catch (err) {
console.error('[api/pulse/activity] GET error:', (err as Error).message);
return NextResponse.json(
{ error: 'Failed to fetch activity' },
{ status: 500 },
);
}
}