Spaces:
Configuration error
Configuration error
| import { NextRequest, NextResponse } from "next/server" | |
| import { prisma } from "@/lib/prisma" | |
| // POST - Record extension analytics | |
| export async function POST(request: NextRequest) { | |
| try { | |
| const body = await request.json() | |
| const { | |
| userId, | |
| deviceId, | |
| action, | |
| platform, | |
| platforms, | |
| promptId, | |
| promptTitle, | |
| promptText, | |
| metadata | |
| } = body | |
| if (!deviceId || !action) { | |
| return NextResponse.json( | |
| { error: "deviceId and action are required" }, | |
| { status: 400 } | |
| ) | |
| } | |
| const analytics = await prisma.extensionAnalytics.create({ | |
| data: { | |
| userId: userId || null, | |
| deviceId, | |
| action, | |
| platform: platform || "unknown", | |
| platforms: platforms || [], | |
| promptId: promptId || null, | |
| promptTitle: promptTitle || null, | |
| promptText: promptText || null, | |
| source: "extension", | |
| metadata: metadata || null, | |
| }, | |
| }) | |
| return NextResponse.json({ success: true, id: analytics.id }) | |
| } catch (error) { | |
| console.error("Extension analytics error:", error) | |
| return NextResponse.json( | |
| { error: "Failed to record analytics" }, | |
| { status: 500 } | |
| ) | |
| } | |
| } | |
| // GET - Fetch extension analytics for a user/device | |
| export async function GET(request: NextRequest) { | |
| try { | |
| const { searchParams } = new URL(request.url) | |
| const userId = searchParams.get("userId") | |
| const deviceId = searchParams.get("deviceId") | |
| const limit = parseInt(searchParams.get("limit") || "50") | |
| if (!userId && !deviceId) { | |
| return NextResponse.json( | |
| { error: "userId or deviceId required" }, | |
| { status: 400 } | |
| ) | |
| } | |
| const where: { userId?: string; deviceId?: string } = {} | |
| if (userId) where.userId = userId | |
| if (deviceId) where.deviceId = deviceId | |
| // Get recent activity | |
| const recentActivity = await prisma.extensionAnalytics.findMany({ | |
| where, | |
| orderBy: { createdAt: "desc" }, | |
| take: limit, | |
| }) | |
| // Get aggregated stats | |
| const stats = await prisma.extensionAnalytics.groupBy({ | |
| by: ["action"], | |
| where, | |
| _count: { action: true }, | |
| }) | |
| const platformStats = await prisma.extensionAnalytics.groupBy({ | |
| by: ["platform"], | |
| where, | |
| _count: { platform: true }, | |
| }) | |
| // Get daily usage for last 30 days | |
| const thirtyDaysAgo = new Date() | |
| thirtyDaysAgo.setDate(thirtyDaysAgo.getDate() - 30) | |
| // Use Prisma's safe query approach | |
| const dailyUsage = await prisma.extensionAnalytics.groupBy({ | |
| by: ['createdAt'], | |
| where: { | |
| ...where, | |
| createdAt: { gte: thirtyDaysAgo }, | |
| }, | |
| _count: { id: true }, | |
| }).then(results => { | |
| // Group by date (day only) | |
| const dateMap = new Map<string, number>() | |
| results.forEach(r => { | |
| const dateStr = r.createdAt.toISOString().split('T')[0] | |
| dateMap.set(dateStr, (dateMap.get(dateStr) || 0) + r._count.id) | |
| }) | |
| return Array.from(dateMap.entries()).map(([date, count]) => ({ date, count })) | |
| }).catch(() => []) | |
| return NextResponse.json({ | |
| recentActivity, | |
| stats: stats.map((s: { action: string; _count: { action: number } }) => ({ | |
| action: s.action, | |
| count: s._count.action | |
| })), | |
| platformStats: platformStats.map((s: { platform: string; _count: { platform: number } }) => ({ | |
| platform: s.platform, | |
| count: s._count.platform | |
| })), | |
| dailyUsage, | |
| }) | |
| } catch (error) { | |
| console.error("Extension analytics fetch error:", error) | |
| return NextResponse.json( | |
| { error: "Failed to fetch analytics" }, | |
| { status: 500 } | |
| ) | |
| } | |
| } | |