← 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 });
}
}