← back to Norma

app/api/archives/route.ts

136 lines

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

/**
 * GET /api/archives
 * List historical emails, workshops, newsletters, campaigns.
 * Optional filters: ?type=email|workshop|newsletter|campaign|template
 *                   ?search=keyword
 *                   ?tags=tag1,tag2
 *                   ?featured=true
 */
export async function GET(request: NextRequest) {
  const auth = requireRole(request, 'admin', 'staff');
  if (auth instanceof NextResponse) return auth;

  try {
    const { searchParams } = new URL(request.url);
    const archiveType = searchParams.get('type');
    const search = searchParams.get('search');
    const tags = searchParams.get('tags');
    const featured = searchParams.get('featured');

    const conditions: string[] = [];
    const values: unknown[] = [];
    let idx = 1;

    if (archiveType) {
      conditions.push(`archive_type = $${idx}`);
      values.push(archiveType);
      idx++;
    }

    if (search) {
      conditions.push(`(title ILIKE $${idx} OR subject ILIKE $${idx} OR content_text ILIKE $${idx} OR campaign_name ILIKE $${idx})`);
      values.push(`%${search}%`);
      idx++;
    }

    if (tags) {
      const tagArray = tags.split(',').map(t => t.trim()).filter(Boolean);
      conditions.push(`tags && $${idx}`);
      values.push(tagArray);
      idx++;
    }

    if (featured === 'true') {
      conditions.push(`is_featured = true`);
    }

    let limit = parseInt(searchParams.get('limit') || '50', 10);
    if (isNaN(limit) || limit < 1) limit = 50;
    if (limit > 200) limit = 200;

    let offset = parseInt(searchParams.get('offset') || '0', 10);
    if (isNaN(offset) || offset < 0) offset = 0;

    const where = conditions.length > 0 ? `WHERE ${conditions.join(' AND ')}` : '';

    const countResult = await query(
      `SELECT COUNT(*)::int AS total FROM historical_archives ${where}`,
      values
    );

    const result = await query(
      `SELECT id, archive_type, title, subject, description, sender, date_sent,
              campaign_name, tags, source, drive_url, metrics, is_featured, usage_count,
              created_at, updated_at
       FROM historical_archives ${where}
       ORDER BY is_featured DESC, date_sent DESC NULLS LAST
       LIMIT $${idx} OFFSET $${idx + 1}`,
      [...values, limit, offset]
    );

    return NextResponse.json({
      archives: result.rows,
      total: countResult.rows[0]?.total || 0,
      limit,
      offset,
    });
  } catch (err) {
    console.error('[api/archives] GET error:', (err as Error).message);
    return NextResponse.json({ error: 'Failed to fetch archives' }, { status: 500 });
  }
}

/**
 * POST /api/archives
 * Create a new historical archive entry.
 */
export async function POST(request: NextRequest) {
  const auth = requireRole(request, 'admin', 'staff');
  if (auth instanceof NextResponse) return auth;

  try {
    const body = await request.json();

    if (!body.archive_type || !body.title) {
      return NextResponse.json({ error: 'archive_type and title are required' }, { status: 400 });
    }

    const result = await query(
      `INSERT INTO historical_archives
       (archive_type, title, subject, description, content_html, content_text,
        sender, recipients, date_sent, campaign_name, tags, source, drive_file_id,
        drive_url, attachments, metrics, is_featured)
       VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17)
       RETURNING *`,
      [
        body.archive_type,
        body.title,
        body.subject || null,
        body.description || null,
        body.content_html || null,
        body.content_text || null,
        body.sender || null,
        body.recipients || null,
        body.date_sent || null,
        body.campaign_name || null,
        body.tags || [],
        body.source || 'drive',
        body.drive_file_id || null,
        body.drive_url || null,
        body.attachments ? JSON.stringify(body.attachments) : '[]',
        body.metrics ? JSON.stringify(body.metrics) : '{}',
        body.is_featured || false,
      ]
    );

    return NextResponse.json({ archive: result.rows[0] }, { status: 201 });
  } catch (err) {
    console.error('[api/archives] POST error:', (err as Error).message);
    return NextResponse.json({ error: 'Failed to create archive' }, { status: 500 });
  }
}