← back to Patty

app/api/settings/route.ts

87 lines

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

/**
 * GET /api/settings
 * Return all app settings as a merged object.
 */
export async function GET(request: NextRequest) {
  const user = verifyAuth(request);
  if (!user) return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });

  try {
    const result = await query(`SELECT key, value FROM app_settings ORDER BY key`);

    const settings: Record<string, unknown> = {};
    for (const row of result.rows) {
      settings[row.key] = row.value;
    }

    // Also get data stats
    const statsQueries = await Promise.all([
      query(`SELECT COUNT(*)::int AS count FROM petitions`).catch(() => ({ rows: [{ count: 0 }] })),
      query(`SELECT COUNT(*)::int AS count FROM signatures`).catch(() => ({ rows: [{ count: 0 }] })),
      query(`SELECT COUNT(*)::int AS count FROM email_subscribers`).catch(() => ({ rows: [{ count: 0 }] })),
      query(`SELECT COUNT(*)::int AS count FROM email_campaigns`).catch(() => ({ rows: [{ count: 0 }] })),
    ]);

    settings.data_stats = {
      total_petitions: statsQueries[0].rows[0]?.count || 0,
      total_signatures: statsQueries[1].rows[0]?.count || 0,
      total_subscribers: statsQueries[2].rows[0]?.count || 0,
      total_campaigns: statsQueries[3].rows[0]?.count || 0,
      last_backup: new Date().toISOString(),
    };

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

/**
 * PATCH /api/settings
 * Update one or more settings sections.
 * Body: { org_profile?: {...}, petition_defaults?: {...}, campaign_settings?: {...}, ai_config?: {...} }
 */
export async function PATCH(request: NextRequest) {
  const user = verifyAuth(request);
  if (!user) return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });

  try {
    const body = await request.json();
    const allowedKeys = ['org_profile', 'petition_defaults', 'campaign_settings', 'ai_config'];
    let updated = 0;

    for (const key of allowedKeys) {
      if (key in body && body[key] !== undefined) {
        await query(
          `INSERT INTO app_settings (key, value, updated_at)
           VALUES ($1, $2, now())
           ON CONFLICT (key) DO UPDATE SET value = $2, updated_at = now()`,
          [key, JSON.stringify(body[key])]
        );
        updated++;
      }
    }

    if (updated === 0) {
      return NextResponse.json({ error: 'No valid settings to update' }, { status: 400 });
    }

    // Re-fetch all settings
    const result = await query(`SELECT key, value FROM app_settings ORDER BY key`);
    const settings: Record<string, unknown> = {};
    for (const row of result.rows) {
      settings[row.key] = row.value;
    }

    return NextResponse.json({ settings, updated });
  } catch (err) {
    console.error('[api/settings] PATCH error:', (err as Error).message);
    return NextResponse.json({ error: 'Failed to update settings' }, { status: 500 });
  }
}