wulf-pulse/app/api/me/queue-preferences/route.ts

102 lines
3.3 KiB
TypeScript
Raw Normal View History

import { NextRequest, NextResponse } from 'next/server';
import { requireAuth } from '@/lib/auth-utils';
import { postgresClient } from '@/lib/services/postgres-client';
// GET /api/me/queue-preferences
// -> { queues: [{ id, label, hidden }], hiddenIds: number[] }
// Returns every active queue with a `hidden` flag for the calling user,
// plus the bare list of hidden queue IDs (for clients that only need that).
//
// PUT /api/me/queue-preferences
// body { hiddenIds: number[] } -> { hiddenIds: number[] }
// Replaces the user's hidden-queue set atomically (full set semantics).
//
// Per-user only — writes target session.user.id, never an id from the body.
export async function GET(): Promise<NextResponse> {
const { session, error } = await requireAuth();
if (error) return error;
try {
const result = await postgresClient.query<{
value: number;
label: string;
hidden: boolean;
}>(
`SELECT q.value, q.label,
(p.queue_id IS NOT NULL) AS hidden
FROM queues q
LEFT JOIN user_queue_preferences p
ON p.queue_id = q.value AND p.user_id = $1
WHERE q.is_active = true
AND (q.is_deleted = false OR q.is_deleted IS NULL)
ORDER BY q.label`,
[session!.user.id],
);
const queues = result.rows.map((r) => ({
id: r.value,
label: r.label,
hidden: r.hidden,
}));
const hiddenIds = queues.filter((q) => q.hidden).map((q) => q.id);
return NextResponse.json({ queues, hiddenIds });
} catch (e) {
console.error('GET /api/me/queue-preferences failed:', e);
return NextResponse.json(
{ error: 'Failed to read queue preferences', message: e instanceof Error ? e.message : 'unknown' },
{ status: 500 },
);
}
}
export async function PUT(request: NextRequest): Promise<NextResponse> {
const { session, error } = await requireAuth();
if (error) return error;
let body: unknown;
try {
body = await request.json();
} catch {
return NextResponse.json(
{ error: 'Invalid JSON', message: 'Request body must be JSON' },
{ status: 400 },
);
}
const raw =
body && typeof body === 'object' && 'hiddenIds' in body
? (body as { hiddenIds: unknown }).hiddenIds
: undefined;
if (!Array.isArray(raw) || !raw.every((v) => Number.isInteger(v))) {
return NextResponse.json(
{ error: 'Invalid input', message: 'hiddenIds must be an array of integers' },
{ status: 400 },
);
}
const hiddenIds = [...new Set(raw as number[])];
const userId = session!.user.id;
try {
await postgresClient.transaction(async (client) => {
await client.query('DELETE FROM user_queue_preferences WHERE user_id = $1', [userId]);
if (hiddenIds.length > 0) {
const placeholders = hiddenIds.map((_, i) => `($1, $${i + 2})`).join(', ');
await client.query(
`INSERT INTO user_queue_preferences (user_id, queue_id) VALUES ${placeholders}
ON CONFLICT (user_id, queue_id) DO NOTHING`,
[userId, ...hiddenIds],
);
}
});
return NextResponse.json({ hiddenIds });
} catch (e) {
console.error('PUT /api/me/queue-preferences failed:', e);
return NextResponse.json(
{ error: 'Failed to update queue preferences', message: e instanceof Error ? e.message : 'unknown' },
{ status: 500 },
);
}
}