All files / src/app/api/admin/support/tickets route.ts

0% Statements 0/108
100% Branches 0/0
0% Functions 0/1
0% Lines 0/108

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109                                                                                                                                                                                                                         
export const dynamic = "force-dynamic";

/**
 * Admin Support Tickets API
 * GET /api/admin/support/tickets - List all tickets with filters
 */

import { NextRequest, NextResponse } from 'next/server';
import {
  withAdmin,
  withErrorHandling,
  ApiError,
  ApiSuccessResponse,
  ApiErrorResponse } from '@/lib/api';
import { } from '@/lib/api/middleware';
import { prisma } from '@/lib/prisma';
import { } from 'next-auth';
import { TicketFilterSchema } from '@/lib/validation/support-schemas';
import { buildTicketWhereClause } from '@/lib/support/ticket-utils';

// ============================================================================
// HANDLERS
// ============================================================================

/**
 * GET /api/admin/support/tickets
 * List all tickets with filters
 */
async function handleGet(
  request: NextRequest
): Promise<NextResponse<ApiSuccessResponse<unknown> | ApiErrorResponse>> {
  // Parse query parameters
  const { searchParams } = request.nextUrl;
  const queryParams: Record<string, string | undefined> = {};

  // Extract all filter params
  const paramNames = [
    'status',
    'priority',
    'category',
    'assignedToId',
    'userId',
    'search',
    'dateFrom',
    'dateTo',
    'page',
    'limit',
    'sortBy',
    'sortOrder',
  ];

  for (const param of paramNames) {
    const value = searchParams.get(param);
    if (value) {
      queryParams[param] = value;
    }
  }

  const filterResult = TicketFilterSchema.safeParse(queryParams);
  if (!filterResult.success) {
    throw ApiError.validation(
      'Invalid query parameters',
      filterResult.error.issues
    );
  }

  const filters = filterResult.data;

  // Build where clause
  const where = buildTicketWhereClause(filters);

  // Get total count
  const total = await prisma.supportTicket.count({ where });

  // Get tickets with pagination
  const tickets = await prisma.supportTicket.findMany({
    where,
    include: {
      user: {
        select: { id: true, name: true, email: true } },
      assignedTo: {
        select: { id: true, name: true, email: true } },
      order: {
        select: { id: true, status: true, total: true } },
      product: {
        select: { id: true, title: true } },
      _count: {
        select: { messages: true } } },
    orderBy: {
      [filters.sortBy]: filters.sortOrder },
    skip: (filters.page - 1) * filters.limit,
    take: filters.limit });

  return NextResponse.json({
    success: true,
    data: tickets,
    pagination: {
      page: filters.page,
      limit: filters.limit,
      total,
      totalPages: Math.ceil(total / filters.limit) } });
}

// ============================================================================
// EXPORTS
// ============================================================================

export const GET = withErrorHandling(withAdmin(handleGet));