← back to Norma
app/api/gmail/contacts/route.ts
73 lines
import { NextRequest, NextResponse } from 'next/server';
import { requireRole } from '@/lib/require-role';
import { query } from '@/lib/db';
export async function GET(req: NextRequest) {
const auth = requireRole(req, 'admin', 'staff');
if (auth instanceof NextResponse) return auth;
const sp = req.nextUrl.searchParams;
const type = sp.get('type') || 'all'; // journalists, congress, organizations, all
const search = sp.get('q') || '';
const state = sp.get('state') || '';
const party = sp.get('party') || '';
const limit = Math.min(parseInt(sp.get('limit') || '100'), 500);
const results: Record<string, unknown[]> = {};
const searchFilter = search ? `%${search}%` : null;
// Journalists
if (type === 'all' || type === 'journalists') {
let jSql = `SELECT id, name, outlet, beat, email, twitter_handle, photo_url, tags, bio, is_active FROM journalists WHERE is_active = true`;
const jParams: unknown[] = [];
if (searchFilter) {
jParams.push(searchFilter, searchFilter, searchFilter);
jSql += ` AND (name ILIKE $1 OR outlet ILIKE $2 OR beat ILIKE $3)`;
}
jSql += ` ORDER BY name LIMIT ${limit}`;
const jRes = await query(jSql, jParams);
results.journalists = jRes.rows;
}
// Congress / Politicians
if (type === 'all' || type === 'congress') {
let pSql = `SELECT id, name, title, party, state, district, office_level, phone, email, website, photo_url, committees, position_student_debt, seniority FROM politicians WHERE 1=1`;
const pParams: unknown[] = [];
let pi = 1;
if (searchFilter) {
pSql += ` AND (name ILIKE $${pi} OR state ILIKE $${pi + 1} OR title ILIKE $${pi + 2})`;
pParams.push(searchFilter, searchFilter, searchFilter);
pi += 3;
}
if (state) {
pSql += ` AND state = $${pi}`;
pParams.push(state);
pi++;
}
if (party) {
pSql += ` AND party = $${pi}`;
pParams.push(party);
pi++;
}
pSql += ` ORDER BY office_level, state, name LIMIT ${limit}`;
const pRes = await query(pSql, pParams);
results.congress = pRes.rows;
}
// Organizations
if (type === 'all' || type === 'organizations') {
let oSql = `SELECT id, name, type, category, state, city, email, phone, website, description FROM organizations WHERE 1=1`;
const oParams: unknown[] = [];
let oi = 1;
if (searchFilter) {
oSql += ` AND (name ILIKE $${oi} OR category ILIKE $${oi + 1} OR state ILIKE $${oi + 2})`;
oParams.push(searchFilter, searchFilter, searchFilter);
oi += 3;
}
oSql += ` ORDER BY name LIMIT ${limit}`;
const oRes = await query(oSql, oParams);
results.organizations = oRes.rows;
}
return NextResponse.json(results);
}