feat: implement core platform features including business directory, admin dashboard, authentication, and API infrastructure
Some checks failed
Build and Push App / build (push) Failing after 16m2s
Some checks failed
Build and Push App / build (push) Failing after 16m2s
This commit is contained in:
@@ -37,14 +37,57 @@ export async function GET(
|
||||
// 3. Get monthly stats (views per day for last 30 days)
|
||||
const thirtyDaysAgo = new Date();
|
||||
thirtyDaysAgo.setDate(thirtyDaysAgo.getDate() - 30);
|
||||
thirtyDaysAgo.setHours(0, 0, 0, 0);
|
||||
|
||||
// Note: Raw query might be needed for group by date in some DBs,
|
||||
// but for now we'll just return the totals for simplicity.
|
||||
const recentEvents = await prisma.analyticsEvent.findMany({
|
||||
where: {
|
||||
createdAt: { gte: thirtyDaysAgo },
|
||||
metadata: {
|
||||
path: ['businessId'],
|
||||
equals: id
|
||||
}
|
||||
},
|
||||
select: {
|
||||
type: true,
|
||||
createdAt: true
|
||||
},
|
||||
orderBy: {
|
||||
createdAt: 'asc'
|
||||
}
|
||||
});
|
||||
|
||||
// 4. Process events into daily stats
|
||||
const statsMap = new Map<string, { date: string, views: number, clicks: number }>();
|
||||
|
||||
// Initialize last 30 days with 0
|
||||
for (let i = 0; i <= 30; i++) {
|
||||
const date = new Date();
|
||||
date.setDate(date.getDate() - i);
|
||||
const dateStr = date.toISOString().split('T')[0];
|
||||
const displayDate = date.toLocaleDateString('fr-FR', { day: 'numeric', month: 'short' });
|
||||
statsMap.set(dateStr, { date: displayDate, views: 0, clicks: 0 });
|
||||
}
|
||||
|
||||
recentEvents.forEach(event => {
|
||||
const dateStr = event.createdAt.toISOString().split('T')[0];
|
||||
if (statsMap.has(dateStr)) {
|
||||
const dayStat = statsMap.get(dateStr)!;
|
||||
if (event.type === 'BUSINESS_VIEW') {
|
||||
dayStat.views++;
|
||||
} else if (event.type === 'BUSINESS_CONTACT_CLICK') {
|
||||
dayStat.clicks++;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Convert Map to sorted array
|
||||
const dailyStats = Array.from(statsMap.values()).reverse(); // Older to newer
|
||||
|
||||
return NextResponse.json({
|
||||
businessId: id,
|
||||
totalViews,
|
||||
contactClicks,
|
||||
dailyStats,
|
||||
updatedAt: new Date().toISOString()
|
||||
});
|
||||
|
||||
|
||||
@@ -1,17 +1,40 @@
|
||||
import { NextRequest, NextResponse } from 'next/server';
|
||||
import prisma from '../../../lib/prisma';
|
||||
import prisma from '@/lib/prisma';
|
||||
import { getGeoInfo } from '@/lib/geo';
|
||||
|
||||
export async function POST(request: NextRequest) {
|
||||
console.log('>>> ANALYTICS API HIT');
|
||||
try {
|
||||
const body = await request.json();
|
||||
console.log('>>> PAYLOAD:', JSON.stringify(body));
|
||||
const { type, path, label, value, metadata } = body;
|
||||
|
||||
if (!type || !path) {
|
||||
return NextResponse.json({ error: 'Type et Path requis' }, { status: 400 });
|
||||
}
|
||||
|
||||
// Extract detailed info from headers
|
||||
const userAgent = request.headers.get('user-agent') || '';
|
||||
const referrer = request.headers.get('referer') || '';
|
||||
const ip = request.headers.get('x-forwarded-for')?.split(',')[0] || '127.0.0.1';
|
||||
|
||||
// Basic User-Agent parsing
|
||||
const isMobile = /mobile/i.test(userAgent);
|
||||
const device = isMobile ? 'Mobile' : 'Desktop';
|
||||
|
||||
let browser = 'Other';
|
||||
if (/chrome|crios/i.test(userAgent)) browser = 'Chrome';
|
||||
else if (/firefox|fxios/i.test(userAgent)) browser = 'Firefox';
|
||||
else if (/safari/i.test(userAgent)) browser = 'Safari';
|
||||
else if (/edge/i.test(userAgent)) browser = 'Edge';
|
||||
|
||||
let os = 'Other';
|
||||
if (/windows/i.test(userAgent)) os = 'Windows';
|
||||
else if (/macintosh/i.test(userAgent)) os = 'macOS';
|
||||
else if (/android/i.test(userAgent)) os = 'Android';
|
||||
else if (/iphone|ipad/i.test(userAgent)) os = 'iOS';
|
||||
|
||||
// Simple Country detection
|
||||
const { country, city } = await getGeoInfo(ip, request.headers);
|
||||
|
||||
const event = await prisma.analyticsEvent.create({
|
||||
data: {
|
||||
type,
|
||||
@@ -19,6 +42,13 @@ export async function POST(request: NextRequest) {
|
||||
label: label || null,
|
||||
value: value || null,
|
||||
metadata: metadata || {},
|
||||
ip,
|
||||
country,
|
||||
browser,
|
||||
os,
|
||||
device,
|
||||
referrer,
|
||||
userId: metadata?.userId || null,
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user