← back to Norma

app/api/settings/news-watch-people/route.ts

133 lines

import { NextRequest, NextResponse } from 'next/server';
import { requireRole } from '@/lib/require-role';
import { query } from '@/lib/db';
import { getOrgId } from '@/lib/orgId';
import { auditLog } from '@/lib/audit';

interface WatchPerson {
  id: number;
  org_id: string | null;
  person_name: string;
  title: string | null;
  keywords: string[] | null;
  is_active: boolean;
  created_at: string;
}

/**
 * GET /api/settings/news-watch-people — List all watch people for the org
 */
export async function GET(request: NextRequest) {
  const auth = requireRole(request, 'admin', 'staff');
  if (auth instanceof NextResponse) return auth;

  const orgId = auth.role === 'admin' ? getOrgId(request) : auth.orgId;

  const result = await query<WatchPerson>(
    `SELECT id, org_id, person_name, title, keywords, is_active, created_at
     FROM news_watch_people
     WHERE ($1::uuid IS NULL OR org_id = $1::uuid)
     ORDER BY created_at DESC`,
    [orgId],
  );

  return NextResponse.json({ people: result.rows });
}

/**
 * POST /api/settings/news-watch-people — Add a new watch person
 */
export async function POST(request: NextRequest) {
  const auth = requireRole(request, 'admin');
  if (auth instanceof NextResponse) return auth;

  const orgId = auth.role === 'admin' ? getOrgId(request) : auth.orgId;
  const body = await request.json();

  const personName = (body.person_name || '').trim();
  if (!personName) {
    return NextResponse.json({ error: 'person_name is required' }, { status: 400 });
  }

  const title = (body.title || '').trim() || null;
  const keywords: string[] = Array.isArray(body.keywords)
    ? body.keywords.filter((k: string) => typeof k === 'string' && k.trim())
    : [];

  const result = await query<WatchPerson>(
    `INSERT INTO news_watch_people (org_id, person_name, title, keywords)
     VALUES ($1, $2, $3, $4)
     RETURNING *`,
    [orgId, personName, title, keywords.length > 0 ? keywords : null],
  );

  await auditLog('news_watch_people.created', 'news_watch_people', String(result.rows[0].id), {
    person_name: personName,
    org_id: orgId,
  });

  return NextResponse.json({ person: result.rows[0] }, { status: 201 });
}

/**
 * PATCH /api/settings/news-watch-people — Toggle active/inactive
 * Body: { id: number, is_active: boolean }
 */
export async function PATCH(request: NextRequest) {
  const auth = requireRole(request, 'admin');
  if (auth instanceof NextResponse) return auth;

  const body = await request.json();
  const { id, is_active } = body;

  if (typeof id !== 'number' || typeof is_active !== 'boolean') {
    return NextResponse.json({ error: 'id (number) and is_active (boolean) required' }, { status: 400 });
  }

  const result = await query<WatchPerson>(
    `UPDATE news_watch_people SET is_active = $1 WHERE id = $2 RETURNING *`,
    [is_active, id],
  );

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

  await auditLog('news_watch_people.toggled', 'news_watch_people', String(id), {
    is_active,
  });

  return NextResponse.json({ person: result.rows[0] });
}

/**
 * DELETE /api/settings/news-watch-people — Remove a watch person
 * Body: { id: number }
 */
export async function DELETE(request: NextRequest) {
  const auth = requireRole(request, 'admin');
  if (auth instanceof NextResponse) return auth;

  const body = await request.json();
  const { id } = body;

  if (typeof id !== 'number') {
    return NextResponse.json({ error: 'id (number) required' }, { status: 400 });
  }

  const result = await query(
    `DELETE FROM news_watch_people WHERE id = $1 RETURNING person_name`,
    [id],
  );

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

  await auditLog('news_watch_people.deleted', 'news_watch_people', String(id), {
    person_name: result.rows[0].person_name,
  });

  return NextResponse.json({ success: true });
}