← back to Norma

app/api/gmail/messages/[id]/mark-read/route.ts

53 lines

// POST /api/gmail/messages/[id]/mark-read — record that the CURRENT user has
// read this message. Idempotent — re-calling does nothing (existing row stays).
// Also flips the legacy global is_read flag so existing list-view logic works.

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

export const runtime = 'nodejs';

export async function POST(request: NextRequest, { params }: { params: Promise<{ id: string }> }) {
  const auth = requireRole(request, 'admin', 'staff', 'intern');
  if (auth instanceof NextResponse) return auth;

  const { id } = await params;
  if (!id) return NextResponse.json({ error: 'missing id' }, { status: 400 });

  // Resolve current user id
  const userRow = await query<{ id: string }>(
    `SELECT id FROM tier_credentials WHERE username = $1 LIMIT 1`,
    [auth.username],
  );
  if (userRow.rows.length === 0) {
    return NextResponse.json({ error: 'session user not found in credentials' }, { status: 403 });
  }
  const userId = userRow.rows[0].id;

  // Verify message exists
  const msgRow = await query<{ id: string }>(
    `SELECT id FROM gmail_messages WHERE id = $1 LIMIT 1`,
    [id],
  );
  if (msgRow.rows.length === 0) {
    return NextResponse.json({ error: 'message not found' }, { status: 404 });
  }

  // Insert read receipt (idempotent via PK conflict)
  await query(
    `INSERT INTO gmail_message_reads (message_id, user_id)
     VALUES ($1, $2)
     ON CONFLICT (message_id, user_id) DO NOTHING`,
    [id, userId],
  );

  // Also flip the legacy is_read flag so existing UI markers still work.
  await query(
    `UPDATE gmail_messages SET is_read = TRUE WHERE id = $1 AND is_read = FALSE`,
    [id],
  );

  return NextResponse.json({ ok: true, message_id: id, user_id: userId });
}