← back to Handbag Auth Nextjs
src/app/api/stats/route.ts
67 lines
import { NextRequest, NextResponse } from 'next/server'
import { prisma } from '@/lib/prisma'
import { rateLimit, getClientIp } from '@/lib/rateLimit'
import { addSecurityHeaders } from '@/lib/securityHeaders'
export async function GET(request: NextRequest) {
try {
// Rate limiting
const clientIp = getClientIp(request)
const rateLimitResult = rateLimit(clientIp, {
windowMs: 60 * 1000,
maxRequests: 60, // 60 requests per minute for stats
})
if (!rateLimitResult.allowed) {
const response = NextResponse.json(
{ success: false, error: 'Rate limit exceeded' },
{ status: 429 }
)
response.headers.set('Retry-After', String(Math.ceil((rateLimitResult.resetTime - Date.now()) / 1000)))
addSecurityHeaders(response)
return response
}
const [
totalListings,
totalDeals,
avgDealResult,
maxDealResult,
brandsResult
] = await Promise.all([
prisma.listing.count({ where: { isActive: 1 } }),
prisma.dealAnalysis.count({ where: { isDeal: 1 } }),
prisma.dealAnalysis.aggregate({
where: { isDeal: 1 },
_avg: { dealPercentage: true }
}),
prisma.dealAnalysis.aggregate({
_max: { dealPercentage: true }
}),
prisma.listing.findMany({
where: { isActive: 1 },
select: { brand: true },
distinct: ['brand']
})
])
const response = NextResponse.json({
success: true,
total_listings: totalListings,
total_deals: totalDeals,
avg_deal_percentage: Math.round((avgDealResult._avg.dealPercentage || 0) * 10) / 10,
best_deal_percentage: Math.round((maxDealResult._max.dealPercentage || 0) * 10) / 10,
brands: brandsResult.filter(b => b.brand).length,
})
addSecurityHeaders(response)
return response
} catch (error) {
console.error('Stats API error:', error)
const response = NextResponse.json(
{ success: false, error: 'Failed to fetch statistics' },
{ status: 500 }
)
addSecurityHeaders(response)
return response
}
}